temp
This commit is contained in:
0
Public/Publish/新建文本文档.txt
Normal file
0
Public/Publish/新建文本文档.txt
Normal file
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -13,13 +14,9 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// 初始化配置与日志
|
// 初始化配置与日志
|
||||||
viper.AutomaticEnv()
|
initConfig()
|
||||||
logger, _ := zap.NewProduction()
|
|
||||||
defer logger.Sync()
|
|
||||||
|
|
||||||
// 数据库初始化
|
// 数据库初始化
|
||||||
db := initDB()
|
initDB()
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
// HTTP 服务配置
|
// HTTP 服务配置
|
||||||
server := initServer(viper.GetString("PORT"), logger)
|
server := initServer(viper.GetString("PORT"), logger)
|
||||||
@@ -57,3 +54,11 @@ func main() {
|
|||||||
logger.Fatal("Server exited with error", zap.Error(err))
|
logger.Fatal("Server exited with error", zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initConfig() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func initDB() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
108
Server/common/config/common-config-branch-dev.json
Normal file
108
Server/common/config/common-config-branch-dev.json
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"logger": {
|
||||||
|
"level": "debug",
|
||||||
|
"max_age": 7,
|
||||||
|
"max_back_up": 128,
|
||||||
|
"max_size": 128,
|
||||||
|
"debug": false
|
||||||
|
},
|
||||||
|
"redis": {
|
||||||
|
"host": "10.0.40.3",
|
||||||
|
"port": 6379,
|
||||||
|
"auth": "123456",
|
||||||
|
"max_idle": 20,
|
||||||
|
"max_active": 100,
|
||||||
|
"db": 0,
|
||||||
|
"tls": false,
|
||||||
|
"user_name": "default"
|
||||||
|
},
|
||||||
|
"etcd": {
|
||||||
|
"host": "http://10.0.40.3",
|
||||||
|
"port": 2379,
|
||||||
|
"ttl": 10,
|
||||||
|
"key_discover": "/discover"
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"driver": "mysql",
|
||||||
|
"host": "10.0.40.3",
|
||||||
|
"port": "3306",
|
||||||
|
"user": "root",
|
||||||
|
"password": "123456"
|
||||||
|
},
|
||||||
|
"mongo": {
|
||||||
|
"user": "root",
|
||||||
|
"password": "superhmm",
|
||||||
|
"ssl_ca_file": "",
|
||||||
|
"host": "10.0.40.3",
|
||||||
|
"port": 27017
|
||||||
|
},
|
||||||
|
"kafka": {
|
||||||
|
"chunkSize": 0,
|
||||||
|
"flushInterval": 1,
|
||||||
|
"brokers": [
|
||||||
|
"10.0.40.3:9092"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jwt": {
|
||||||
|
"secret": "ZMpy1gIxRevtcIwoW1qA84YAcWj4cjrEhPUebOiB8hUXkiwOfobJxeklH4ZO1VE1",
|
||||||
|
"expires": 30
|
||||||
|
},
|
||||||
|
"tencent_video_call": {
|
||||||
|
"appID": 1600034485,
|
||||||
|
"secretKey": "9c2e7aab5c318194ee815ee0a5162ea9ab0b0bce981311d5ce08d26c5e9df9e0",
|
||||||
|
"callBackKey": "Pv3JD4RJXBCo",
|
||||||
|
"prefix": "branch_dev",
|
||||||
|
"tencent_asr_cloud_os": {
|
||||||
|
"bucket": "meeting-test-1306984848",
|
||||||
|
"region": "ap-guangzhou",
|
||||||
|
"bucketURL": "https://meeting-test-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://meeting-test-1306984848.ci.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIWorkflows": {
|
||||||
|
"asr_workflow": {
|
||||||
|
"name": "cover_asr",
|
||||||
|
"workflowId": "wc700505871f849908f56f30533cb54ce"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tencent_cloud_os": {
|
||||||
|
"bucketURL": "https://ecosmos-test-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"serviceURL": "https://cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"batchURL": "https://AKID27MnCY2eFsWCnKlItThxt1EubMriDewC.cos-control.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://ecosmos-test-1306984848.ci.ap-guangzhou.myqcloud.com"
|
||||||
|
},
|
||||||
|
"tencent_sdk_common": {
|
||||||
|
"secretId": "AKID27MnCY2eFsWCnKlItThxt1EubMriDewC",
|
||||||
|
"secretKey": "IWdfaTTN8Y6g8Q4qdRH3BUsQySCjOKiC"
|
||||||
|
},
|
||||||
|
"back_http": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "10.0.40.9:7098",
|
||||||
|
"xkey": "lkAsgl2sShgfnDweJLJSNGLSNG1234sKE58dgd"
|
||||||
|
},
|
||||||
|
"us": {
|
||||||
|
"public_key": "4eZBdZBQvR7JdD3Q3WMHna67b0BPf7U6O",
|
||||||
|
"private_key": "FugwvTjts8rJ2eYiLTatH0FK2n3zjhhWP9EsXXbmDhvy",
|
||||||
|
"bucket_name": "ecosmos-test",
|
||||||
|
"file_host": "cn-wlcb.ufileos.com",
|
||||||
|
"bucket_host": "api.ucloud.cn",
|
||||||
|
"verfiy_upload_md5": true,
|
||||||
|
"us_host_path": "https"
|
||||||
|
},
|
||||||
|
"ai_server": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "106.52.14.61:15002"
|
||||||
|
},
|
||||||
|
"elecnest": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "id.elecnest.cn"
|
||||||
|
},
|
||||||
|
"open_log": true,
|
||||||
|
"wechat_mini": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "api.weixin.qq.com",
|
||||||
|
"envVersion": "trial",
|
||||||
|
"getWxACodeUnLimitPath": "/wxa/getwxacodeunlimit",
|
||||||
|
"generateUrlLinkPath": "/wxa/generate_urllink"
|
||||||
|
}
|
||||||
|
}
|
||||||
108
Server/common/config/common-config-branch-test.json
Normal file
108
Server/common/config/common-config-branch-test.json
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"logger": {
|
||||||
|
"level": "debug",
|
||||||
|
"max_age": 7,
|
||||||
|
"max_back_up": 128,
|
||||||
|
"max_size": 128,
|
||||||
|
"debug": false
|
||||||
|
},
|
||||||
|
"redis": {
|
||||||
|
"host": "10.0.0.12",
|
||||||
|
"port": 6379,
|
||||||
|
"auth": "Q3GNWg!TEsmkURuSYe9",
|
||||||
|
"max_idle": 20,
|
||||||
|
"max_active": 100,
|
||||||
|
"db": 0,
|
||||||
|
"tls": false,
|
||||||
|
"user_name": "default"
|
||||||
|
},
|
||||||
|
"etcd": {
|
||||||
|
"host": "http://10.0.0.12",
|
||||||
|
"port": 2379,
|
||||||
|
"ttl": 10,
|
||||||
|
"key_discover": "/discover"
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"driver": "mysql",
|
||||||
|
"host": "10.0.0.12",
|
||||||
|
"port": "3306",
|
||||||
|
"user": "root",
|
||||||
|
"password": "MwrC5zcZ8HQ7BB=qb4K8"
|
||||||
|
},
|
||||||
|
"mongo": {
|
||||||
|
"user": "root",
|
||||||
|
"password": "eExeaWF=dQzJpkMtc9kb",
|
||||||
|
"ssl_ca_file": "",
|
||||||
|
"host": "10.0.0.12",
|
||||||
|
"port": 27017
|
||||||
|
},
|
||||||
|
"kafka": {
|
||||||
|
"chunkSize": 0,
|
||||||
|
"flushInterval": 1,
|
||||||
|
"brokers": [
|
||||||
|
"10.0.0.12:9092"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jwt": {
|
||||||
|
"secret": "ZMpy1gIxRevtcIwoW1qA84YAcWj4cjrEhPUebOiB8hUXkiwOfobJxeklH4ZO1VE4",
|
||||||
|
"expires": 30
|
||||||
|
},
|
||||||
|
"tencent_video_call": {
|
||||||
|
"appID": 1600034485,
|
||||||
|
"secretKey": "9c2e7aab5c318194ee815ee0a5162ea9ab0b0bce981311d5ce08d26c5e9df9e0",
|
||||||
|
"callBackKey": "Pv3JD4RJXBCo",
|
||||||
|
"prefix": "branch_test",
|
||||||
|
"tencent_asr_cloud_os": {
|
||||||
|
"bucket": "meeting-test-1306984848",
|
||||||
|
"region": "ap-guangzhou",
|
||||||
|
"bucketURL": "https://meeting-test-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://meeting-test-1306984848.ci.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIWorkflows": {
|
||||||
|
"asr_workflow": {
|
||||||
|
"name": "cover_asr",
|
||||||
|
"workflowId": "wc700505871f849908f56f30533cb54ce"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tencent_cloud_os": {
|
||||||
|
"bucketURL": "https://ecosmos-test-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"serviceURL": "https://cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"batchURL": "https://AKID27MnCY2eFsWCnKlItThxt1EubMriDewC.cos-control.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://ecosmos-test-1306984848.ci.ap-guangzhou.myqcloud.com"
|
||||||
|
},
|
||||||
|
"tencent_sdk_common": {
|
||||||
|
"secretId": "AKID27MnCY2eFsWCnKlItThxt1EubMriDewC",
|
||||||
|
"secretKey": "IWdfaTTN8Y6g8Q4qdRH3BUsQySCjOKiC"
|
||||||
|
},
|
||||||
|
"back_http": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "10.0.0.12:7098",
|
||||||
|
"xkey": "lkAsgl2sShgfnDweJLJSNGLSNG1234sKE58dgd"
|
||||||
|
},
|
||||||
|
"us": {
|
||||||
|
"public_key": "4eZBdZBQvR7JdD3Q3WMHna67b0BPf7U6O",
|
||||||
|
"private_key": "FugwvTjts8rJ2eYiLTatH0FK2n3zjhhWP9EsXXbmDhvy",
|
||||||
|
"bucket_name": "ecosmos-test",
|
||||||
|
"file_host": "cn-wlcb.ufileos.com",
|
||||||
|
"bucket_host": "api.ucloud.cn",
|
||||||
|
"verfiy_upload_md5": true,
|
||||||
|
"us_host_path": "https"
|
||||||
|
},
|
||||||
|
"ai_server": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "106.52.14.61:15002"
|
||||||
|
},
|
||||||
|
"elecnest": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "id.elecnest.cn"
|
||||||
|
},
|
||||||
|
"open_log": true,
|
||||||
|
"wechat_mini": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "api.weixin.qq.com",
|
||||||
|
"envVersion": "trial",
|
||||||
|
"getWxACodeUnLimitPath": "/wxa/getwxacodeunlimit",
|
||||||
|
"generateUrlLinkPath": "/wxa/generate_urllink"
|
||||||
|
}
|
||||||
|
}
|
||||||
108
Server/common/config/common-config-prod.json
Normal file
108
Server/common/config/common-config-prod.json
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"logger": {
|
||||||
|
"level": "debug",
|
||||||
|
"max_age": 7,
|
||||||
|
"max_back_up": 128,
|
||||||
|
"max_size": 128,
|
||||||
|
"debug": false
|
||||||
|
},
|
||||||
|
"redis": {
|
||||||
|
"host": "10.0.10.9",
|
||||||
|
"port": 6379,
|
||||||
|
"auth": "ZzC2gCVuR52!z",
|
||||||
|
"max_idle": 20,
|
||||||
|
"max_active": 100,
|
||||||
|
"db": 1,
|
||||||
|
"tls": false,
|
||||||
|
"user_name": "default"
|
||||||
|
},
|
||||||
|
"etcd": {
|
||||||
|
"host": "http://10.0.0.7",
|
||||||
|
"port": 2379,
|
||||||
|
"ttl": 20,
|
||||||
|
"key_discover": "/discover"
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"driver": "mysql",
|
||||||
|
"host": "10.0.5.10",
|
||||||
|
"port": "3306",
|
||||||
|
"user": "root",
|
||||||
|
"password": "d3tnt4J2aWRg7fZ52M"
|
||||||
|
},
|
||||||
|
"mongo": {
|
||||||
|
"user": "mongouser",
|
||||||
|
"password": "xEti2JhEgI!m",
|
||||||
|
"ssl_ca_file": "",
|
||||||
|
"host": "10.0.2.9",
|
||||||
|
"port": 27017
|
||||||
|
},
|
||||||
|
"kafka": {
|
||||||
|
"chunkSize": 0,
|
||||||
|
"flushInterval": 1,
|
||||||
|
"brokers": [
|
||||||
|
"10.0.12.16:9092"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jwt": {
|
||||||
|
"secret": "ZMpy1gIxRevtcIwoW1qA84YAcWj4cjrEhPUebOiB8hUXkiwOfobJxeklH4ZO1VE3",
|
||||||
|
"expires": 30
|
||||||
|
},
|
||||||
|
"tencent_video_call": {
|
||||||
|
"appID": 1600003528,
|
||||||
|
"secretKey": "8188013dbe9f35305c58a2f8964fbf330f9e1de4a60827966c91a47b9f2ae607",
|
||||||
|
"callBackKey": "MzPBm3csloMHkXmEcvl",
|
||||||
|
"prefix": "prod",
|
||||||
|
"tencent_asr_cloud_os": {
|
||||||
|
"bucket": "meeting-prod-1306984848",
|
||||||
|
"region": "ap-guangzhou",
|
||||||
|
"bucketURL": "https://meeting-prod-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://meeting-prod-1306984848.ci.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIWorkflows": {
|
||||||
|
"asr_workflow": {
|
||||||
|
"name": "prod_cover_asr",
|
||||||
|
"workflowId": "w2d30647561e341f19342d684c92e483a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tencent_cloud_os": {
|
||||||
|
"bucketURL": "https://ecosmos-prod-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"serviceURL": "https://cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"batchURL": "https://AKID27MnCY2eFsWCnKlItThxt1EubMriDewC.cos-control.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://ecosmos-prod-1306984848.ci.ap-guangzhou.myqcloud.com"
|
||||||
|
},
|
||||||
|
"tencent_sdk_common": {
|
||||||
|
"secretId": "AKID27MnCY2eFsWCnKlItThxt1EubMriDewC",
|
||||||
|
"secretKey": "IWdfaTTN8Y6g8Q4qdRH3BUsQySCjOKiC"
|
||||||
|
},
|
||||||
|
"back_http": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "10.0.0.7:7098",
|
||||||
|
"xkey": "lkAsgl2sShgfnDweJLJSNGLSNG1234sKE58dgd"
|
||||||
|
},
|
||||||
|
"us": {
|
||||||
|
"public_key": "4eZBdZBQvR7JdD3Q3WMHna67b0BPf7U6O",
|
||||||
|
"private_key": "FugwvTjts8rJ2eYiLTatH0FK2n3zjhhWP9EsXXbmDhvy",
|
||||||
|
"bucket_name": "ecosmos",
|
||||||
|
"file_host": "cn-wlcb.ufileos.com",
|
||||||
|
"bucket_host": "api.ucloud.cn",
|
||||||
|
"verfiy_upload_md5": true,
|
||||||
|
"us_host_path": "https"
|
||||||
|
},
|
||||||
|
"ai_server": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "106.52.14.61:15002"
|
||||||
|
},
|
||||||
|
"elecnest": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "identify.elecnest.com"
|
||||||
|
},
|
||||||
|
"open_log": true,
|
||||||
|
"wechat_mini": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "api.weixin.qq.com",
|
||||||
|
"envVersion": "release",
|
||||||
|
"getWxACodeUnLimitPath": "/wxa/getwxacodeunlimit",
|
||||||
|
"generateUrlLinkPath": "/wxa/generate_urllink"
|
||||||
|
}
|
||||||
|
}
|
||||||
108
Server/common/config/common-config-trunk-dev.json
Normal file
108
Server/common/config/common-config-trunk-dev.json
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"logger": {
|
||||||
|
"level": "debug",
|
||||||
|
"max_age": 7,
|
||||||
|
"max_back_up": 128,
|
||||||
|
"max_size": 128,
|
||||||
|
"debug": false
|
||||||
|
},
|
||||||
|
"redis": {
|
||||||
|
"host": "10.0.40.9",
|
||||||
|
"port": 6379,
|
||||||
|
"auth": "superhmm",
|
||||||
|
"max_idle": 20,
|
||||||
|
"max_active": 100,
|
||||||
|
"db": 0,
|
||||||
|
"tls": false,
|
||||||
|
"user_name": "default"
|
||||||
|
},
|
||||||
|
"etcd": {
|
||||||
|
"host": "http://10.0.40.9",
|
||||||
|
"port": 2379,
|
||||||
|
"ttl": 10,
|
||||||
|
"key_discover": "/discover"
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"driver": "mysql",
|
||||||
|
"host": "10.0.40.9",
|
||||||
|
"port": "3306",
|
||||||
|
"user": "root",
|
||||||
|
"password": "123456"
|
||||||
|
},
|
||||||
|
"mongo": {
|
||||||
|
"user": "root",
|
||||||
|
"password": "superhmm",
|
||||||
|
"ssl_ca_file": "",
|
||||||
|
"host": "10.0.40.9",
|
||||||
|
"port": 27017
|
||||||
|
},
|
||||||
|
"kafka": {
|
||||||
|
"chunkSize": 0,
|
||||||
|
"flushInterval": 1,
|
||||||
|
"brokers": [
|
||||||
|
"10.0.40.9:9092"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jwt": {
|
||||||
|
"secret": "ZMpy1gIxRevtcIwoW1qA84YAcWj4cjrEhPUebOiB8hUXkiwOfobJxeklH4ZO1VE1",
|
||||||
|
"expires": 30
|
||||||
|
},
|
||||||
|
"tencent_video_call": {
|
||||||
|
"appID": 1600034485,
|
||||||
|
"secretKey": "9c2e7aab5c318194ee815ee0a5162ea9ab0b0bce981311d5ce08d26c5e9df9e0",
|
||||||
|
"callBackKey": "RSHRgskxwUauX6JyTb7m",
|
||||||
|
"prefix": "dev",
|
||||||
|
"tencent_asr_cloud_os": {
|
||||||
|
"bucket": "meeting-dev-1306984848",
|
||||||
|
"region": "ap-guangzhou",
|
||||||
|
"bucketURL": "https://meeting-dev-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://meeting-dev-1306984848.ci.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIWorkflows": {
|
||||||
|
"asr_workflow": {
|
||||||
|
"name": "cover_asr",
|
||||||
|
"workflowId": "w8b3ece33cd2d4b28a373779dc3a93941"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tencent_cloud_os": {
|
||||||
|
"bucketURL": "https://ecosmos-dev-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"serviceURL": "https://cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"batchURL": "https://AKID27MnCY2eFsWCnKlItThxt1EubMriDewC.cos-control.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://ecosmos-dev-1306984848.ci.ap-guangzhou.myqcloud.com"
|
||||||
|
},
|
||||||
|
"tencent_sdk_common": {
|
||||||
|
"secretId": "AKID27MnCY2eFsWCnKlItThxt1EubMriDewC",
|
||||||
|
"secretKey": "IWdfaTTN8Y6g8Q4qdRH3BUsQySCjOKiC"
|
||||||
|
},
|
||||||
|
"back_http": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "10.0.40.9:7098",
|
||||||
|
"xkey": "lkAsgl2sShgfnDweJLJSNGLSNG1234sKE58dgd"
|
||||||
|
},
|
||||||
|
"us": {
|
||||||
|
"public_key": "4eZBdZBQvR7JdD3Q3WMHna67b0BPf7U6O",
|
||||||
|
"private_key": "FugwvTjts8rJ2eYiLTatH0FK2n3zjhhWP9EsXXbmDhvy",
|
||||||
|
"bucket_name": "ecosmos-test",
|
||||||
|
"file_host": "cn-wlcb.ufileos.com",
|
||||||
|
"bucket_host": "api.ucloud.cn",
|
||||||
|
"verfiy_upload_md5": true,
|
||||||
|
"us_host_path": "https"
|
||||||
|
},
|
||||||
|
"ai_server": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "106.52.14.61:15002"
|
||||||
|
},
|
||||||
|
"elecnest": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "id.elecnest.cn"
|
||||||
|
},
|
||||||
|
"openLog": false,
|
||||||
|
"wechat_mini": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "api.weixin.qq.com",
|
||||||
|
"envVersion": "develop",
|
||||||
|
"getWxACodeUnLimitPath": "/wxa/getwxacodeunlimit",
|
||||||
|
"generateUrlLinkPath": "/wxa/generate_urllink"
|
||||||
|
}
|
||||||
|
}
|
||||||
108
Server/common/config/common-config-trunk-test.json
Normal file
108
Server/common/config/common-config-trunk-test.json
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"logger": {
|
||||||
|
"level": "debug",
|
||||||
|
"max_age": 7,
|
||||||
|
"max_back_up": 128,
|
||||||
|
"max_size": 128,
|
||||||
|
"debug": false
|
||||||
|
},
|
||||||
|
"redis": {
|
||||||
|
"host": "10.0.0.15",
|
||||||
|
"port": 6379,
|
||||||
|
"auth": "Q3GNWg!TEsmkURuSYe9",
|
||||||
|
"max_idle": 20,
|
||||||
|
"max_active": 100,
|
||||||
|
"db": 0,
|
||||||
|
"tls": false,
|
||||||
|
"user_name": "default"
|
||||||
|
},
|
||||||
|
"etcd": {
|
||||||
|
"host": "http://10.0.0.15",
|
||||||
|
"port": 2379,
|
||||||
|
"ttl": 10,
|
||||||
|
"key_discover": "/discover"
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"driver": "mysql",
|
||||||
|
"host": "10.0.0.15",
|
||||||
|
"port": "3306",
|
||||||
|
"user": "root",
|
||||||
|
"password": "MwrC5zcZ8HQ7BB=qb4K8"
|
||||||
|
},
|
||||||
|
"mongo": {
|
||||||
|
"user": "root",
|
||||||
|
"password": "eExeaWF=dQzJpkMtc9kb",
|
||||||
|
"ssl_ca_file": "",
|
||||||
|
"host": "134.175.247.234",
|
||||||
|
"port": 27017
|
||||||
|
},
|
||||||
|
"kafka": {
|
||||||
|
"chunkSize": 0,
|
||||||
|
"flushInterval": 1,
|
||||||
|
"brokers": [
|
||||||
|
"10.0.0.15:9092"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"jwt": {
|
||||||
|
"secret": "ZMpy1gIxRevtcIwoW1qA84YAcWj4cjrEhPUebOiB8hUXkiwOfobJxeklH4ZO1VE2",
|
||||||
|
"expires": 30
|
||||||
|
},
|
||||||
|
"tencent_video_call": {
|
||||||
|
"appID": 1600034485,
|
||||||
|
"secretKey": "9c2e7aab5c318194ee815ee0a5162ea9ab0b0bce981311d5ce08d26c5e9df9e0",
|
||||||
|
"callBackKey": "Pv3JD4RJXBCo",
|
||||||
|
"prefix": "test",
|
||||||
|
"tencent_asr_cloud_os": {
|
||||||
|
"bucket": "meeting-test-1306984848",
|
||||||
|
"region": "ap-guangzhou",
|
||||||
|
"bucketURL": "https://meeting-test-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://meeting-test-1306984848.ci.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIWorkflows": {
|
||||||
|
"asr_workflow": {
|
||||||
|
"name": "cover_asr",
|
||||||
|
"workflowId": "wc700505871f849908f56f30533cb54ce"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tencent_cloud_os": {
|
||||||
|
"bucketURL": "https://ecosmos-test-1306984848.cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"serviceURL": "https://cos.ap-guangzhou.myqcloud.com",
|
||||||
|
"batchURL": "https://AKID27MnCY2eFsWCnKlItThxt1EubMriDewC.cos-control.ap-guangzhou.myqcloud.com",
|
||||||
|
"CIURL": "https://ecosmos-test-1306984848.ci.ap-guangzhou.myqcloud.com"
|
||||||
|
},
|
||||||
|
"tencent_sdk_common": {
|
||||||
|
"secretId": "AKID27MnCY2eFsWCnKlItThxt1EubMriDewC",
|
||||||
|
"secretKey": "IWdfaTTN8Y6g8Q4qdRH3BUsQySCjOKiC"
|
||||||
|
},
|
||||||
|
"back_http": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "10.0.0.15:7098",
|
||||||
|
"xkey": "lkAsgl2sShgfnDweJLJSNGLSNG1234sKE58dgd"
|
||||||
|
},
|
||||||
|
"us": {
|
||||||
|
"public_key": "4eZBdZBQvR7JdD3Q3WMHna67b0BPf7U6O",
|
||||||
|
"private_key": "FugwvTjts8rJ2eYiLTatH0FK2n3zjhhWP9EsXXbmDhvy",
|
||||||
|
"bucket_name": "ecosmos-test",
|
||||||
|
"file_host": "cn-wlcb.ufileos.com",
|
||||||
|
"bucket_host": "api.ucloud.cn",
|
||||||
|
"verfiy_upload_md5": true,
|
||||||
|
"us_host_path": "https"
|
||||||
|
},
|
||||||
|
"ai_server": {
|
||||||
|
"scheme": "http",
|
||||||
|
"host": "106.52.14.61:15002"
|
||||||
|
},
|
||||||
|
"elecnest": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "id.elecnest.cn"
|
||||||
|
},
|
||||||
|
"open_log": true,
|
||||||
|
"wechat_mini": {
|
||||||
|
"scheme": "https",
|
||||||
|
"host": "api.weixin.qq.com",
|
||||||
|
"envVersion": "trial",
|
||||||
|
"getWxACodeUnLimitPath": "/wxa/getwxacodeunlimit",
|
||||||
|
"generateUrlLinkPath": "/wxa/generate_urllink"
|
||||||
|
}
|
||||||
|
}
|
||||||
166
Server/common/config/config.go
Normal file
166
Server/common/config/config.go
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type (
|
||||||
|
LoggerConfig struct {
|
||||||
|
Level string `json:"level"`
|
||||||
|
MaxAge int `json:"max_age"`
|
||||||
|
MaxBackUp int `json:"max_back_up"`
|
||||||
|
MaxSize int `json:"max_size"`
|
||||||
|
Debug bool `json:"debug"`
|
||||||
|
}
|
||||||
|
|
||||||
|
RedisConfig struct {
|
||||||
|
Host string `json:"host" env:"REDIS_HOST"`
|
||||||
|
Port int `json:"port" env:"REDIS_PORT"`
|
||||||
|
Auth string `json:"auth" env:"REDIS_AUTH"`
|
||||||
|
MaxIdle int `json:"max_idle" env:"REDIS_MAX_IDLE"`
|
||||||
|
MaxActive int `json:"max_active" env:"REDIS_MAX_ACTIVE"`
|
||||||
|
Db int `json:"db" env:"REDIS_DB"`
|
||||||
|
Tls bool `json:"tls"`
|
||||||
|
UserName string `json:"user_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
EtcdConfig struct {
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
TTL int64 `json:"ttl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
JWTConfig struct {
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
Expires int `json:"expires"`
|
||||||
|
}
|
||||||
|
|
||||||
|
TableConfig struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectionInfo struct {
|
||||||
|
WebSocket string `json:"web_socket"`
|
||||||
|
HttpAddr string `json:"http_addr"`
|
||||||
|
GameSocketHost string `json:"game_socket_host"`
|
||||||
|
GameSocketPort int `json:"game_socket_port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
MysqlConfig struct {
|
||||||
|
Driver string `json:"driver"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port string `json:"port"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
DbName string `json:"db_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
MongoConfig struct {
|
||||||
|
User string `json:"user"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
SSLCaFile string `json:"ssl_ca_file"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
GamesInfo struct {
|
||||||
|
ConnectInfo []ConnectionInfo `json:"connect_info"`
|
||||||
|
}
|
||||||
|
TencentVideo struct {
|
||||||
|
AppID int `json:"appID"`
|
||||||
|
Key string `json:"secretKey"`
|
||||||
|
CallBackKey string `json:"callBackKey"`
|
||||||
|
Prefix string `json:"prefix"`
|
||||||
|
TencentAsrCloudOS TencentAsrCloudOS `json:"tencent_asr_cloud_os"`
|
||||||
|
}
|
||||||
|
TencentAsr struct {
|
||||||
|
AppID string `json:"appID"`
|
||||||
|
Key string `json:"secretKey"`
|
||||||
|
CallBackKey string `json:"callBackKey"`
|
||||||
|
Prefix string `json:"prefix"`
|
||||||
|
}
|
||||||
|
TencentAsrCloudOS struct {
|
||||||
|
Bucket string `json:"bucket"`
|
||||||
|
|
||||||
|
Region string `json:"region"`
|
||||||
|
|
||||||
|
BucketURL string `json:"bucketURL"`
|
||||||
|
|
||||||
|
CIURL string `json:"CIURL"`
|
||||||
|
|
||||||
|
CIWorkflows map[string]TencentCIWorkflows `json:"CIWorkflows"`
|
||||||
|
}
|
||||||
|
TencentCIWorkflows struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
WorkflowId string `json:"workflowId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
TencentCloudOS struct {
|
||||||
|
BucketURL string `json:"bucketURL"`
|
||||||
|
ServiceURL string `json:"serviceURL"`
|
||||||
|
BatchURL string `json:"batchURL"`
|
||||||
|
CIURL string `json:"CIURL"`
|
||||||
|
}
|
||||||
|
|
||||||
|
TencentSdkCommon struct {
|
||||||
|
SecretId string `json:"secretId"`
|
||||||
|
SecretKey string `json:"secretKey"`
|
||||||
|
}
|
||||||
|
BackHttp struct {
|
||||||
|
Scheme string `json:"scheme"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Xkey string `json:"xkey"`
|
||||||
|
}
|
||||||
|
Us struct {
|
||||||
|
PublicKey string `json:"public_key"`
|
||||||
|
PrivateKey string `json:"private_key"`
|
||||||
|
BucketHost string `json:"bucket_host"`
|
||||||
|
BucketName string `json:"bucket_name"`
|
||||||
|
FileHost string `json:"file_host"`
|
||||||
|
VerifyUploadMD5 bool `json:"verfiy_upload_md5"`
|
||||||
|
Endpoint string `json:"endpoint"`
|
||||||
|
UsHostPath string `json:"us_host_path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
AIServer struct {
|
||||||
|
Scheme string `json:"scheme"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
}
|
||||||
|
|
||||||
|
KafkaConfig struct {
|
||||||
|
Brokers []string `json:"brokers"`
|
||||||
|
ChunkSize int `json:"chunkSize"`
|
||||||
|
FlushInterval int `json:"flushInterval"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Elecnest struct {
|
||||||
|
Scheme string `json:"scheme"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
}
|
||||||
|
|
||||||
|
WechatMini struct {
|
||||||
|
Scheme string `json:"scheme"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
EnvVersion string `json:"envVersion"`
|
||||||
|
GetWxACodeUnLimitPath string `json:"getWxACodeUnLimitPath"`
|
||||||
|
GenerateUrlLinkPath string `json:"generateUrlLinkPath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonConfig struct {
|
||||||
|
Logger LoggerConfig `json:"logger"`
|
||||||
|
Redis RedisConfig `json:"redis"`
|
||||||
|
Etcd EtcdConfig `json:"etcd"`
|
||||||
|
Tables TableConfig `json:"tables"`
|
||||||
|
JWT JWTConfig `json:"jwt"`
|
||||||
|
MysqlConfig MysqlConfig `json:"mysql"`
|
||||||
|
MongoConfig MongoConfig `json:"mongo"`
|
||||||
|
Kafka KafkaConfig `json:"kafka"`
|
||||||
|
TencentVideo TencentVideo `json:"tencent_video_call"`
|
||||||
|
TencentCloudOS TencentCloudOS `json:"tencent_cloud_os"`
|
||||||
|
TencentSdkCommon TencentSdkCommon `json:"tencent_sdk_common"`
|
||||||
|
GamesInfo GamesInfo `json:"games"`
|
||||||
|
Back BackHttp `json:"back_http"`
|
||||||
|
Us Us `json:"us"`
|
||||||
|
AIServer AIServer `json:"ai_server"`
|
||||||
|
Elecnest *Elecnest `json:"elecnest"`
|
||||||
|
OpenLog bool `json:"open_log"`
|
||||||
|
WechatMini *WechatMini `json:"wechat_mini"`
|
||||||
|
}
|
||||||
|
)
|
||||||
29
Server/common/db/etcd/etcd.go
Normal file
29
Server/common/db/etcd/etcd.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package etcd
|
||||||
|
|
||||||
|
import (
|
||||||
|
commonConfig "common/config"
|
||||||
|
"fmt"
|
||||||
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var etcdClient *clientv3.Client
|
||||||
|
|
||||||
|
func Init(cfg *commonConfig.EtcdConfig) error {
|
||||||
|
client, err := clientv3.New(clientv3.Config{
|
||||||
|
Endpoints: []string{fmt.Sprintf("%v:%v", cfg.Host, cfg.Port)},
|
||||||
|
DialTimeout: 0,
|
||||||
|
})
|
||||||
|
etcdClient = client
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Close() error {
|
||||||
|
if etcdClient != nil {
|
||||||
|
return etcdClient.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Client() *clientv3.Client {
|
||||||
|
return etcdClient
|
||||||
|
}
|
||||||
77
Server/common/db/mongo/mongo.go
Normal file
77
Server/common/db/mongo/mongo.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package mongo
|
||||||
|
|
||||||
|
import (
|
||||||
|
commonConfig "common/config"
|
||||||
|
"common/log"
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"go.mongodb.org/mongo-driver/event"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
MDB *mongo.Client
|
||||||
|
DefaultDB *mongo.Database
|
||||||
|
ChatDB *mongo.Database
|
||||||
|
ErrNoDocuments = mongo.ErrNoDocuments
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(cfg *commonConfig.MongoConfig) error {
|
||||||
|
dialect := ""
|
||||||
|
if len(cfg.User) > 0 && len(cfg.Password) > 0 {
|
||||||
|
dialect = fmt.Sprintf("mongodb://%s:%s@%s:%d/admin?appname=MongoDB", cfg.User, cfg.Password, cfg.Host, cfg.Port)
|
||||||
|
} else {
|
||||||
|
dialect = fmt.Sprintf("mongodb://%s:%d/admin?readPreference=primary&appname=MongoDB&ssl=false", cfg.Host, cfg.Port)
|
||||||
|
}
|
||||||
|
var clientOptions *options.ClientOptions
|
||||||
|
if len(cfg.SSLCaFile) > 0 {
|
||||||
|
data, err := ioutil.ReadFile(cfg.SSLCaFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dialect += "&ssl=true"
|
||||||
|
roots := x509.NewCertPool()
|
||||||
|
roots.AppendCertsFromPEM(data)
|
||||||
|
clientOptions = options.Client().ApplyURI(dialect).SetTLSConfig(&tls.Config{
|
||||||
|
RootCAs: roots,
|
||||||
|
//InsecureSkipVerify: true,
|
||||||
|
}).SetRetryWrites(false)
|
||||||
|
} else {
|
||||||
|
dialect += "&ssl=false"
|
||||||
|
clientOptions = options.Client().ApplyURI(dialect).SetRetryWrites(false)
|
||||||
|
}
|
||||||
|
monitor := &event.CommandMonitor{
|
||||||
|
Started: func(ctx context.Context, startedEvent *event.CommandStartedEvent) {
|
||||||
|
log.Infof("mongoDB Command started %v %v", startedEvent.CommandName, startedEvent.Command.String())
|
||||||
|
},
|
||||||
|
Failed: func(ctx context.Context, failedEvent *event.CommandFailedEvent) {
|
||||||
|
log.Errorf("mongoDB Command error %v %v", failedEvent.CommandName, failedEvent.Failure)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
clientOptions.SetMonitor(monitor)
|
||||||
|
client, err := mongo.Connect(context.Background(), clientOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = client.Ping(context.Background(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB = client
|
||||||
|
DefaultDB = MDB.Database("ecosmos")
|
||||||
|
ChatDB = MDB.Database("ecosmos_chat")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Close() error {
|
||||||
|
if MDB != nil {
|
||||||
|
return MDB.Disconnect(context.Background())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
90
Server/common/db/mysql/mysql.go
Normal file
90
Server/common/db/mysql/mysql.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
commonConfig "common/config"
|
||||||
|
"common/log"
|
||||||
|
"common/query"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DBNameEcosmos = "ecosmos"
|
||||||
|
DBNameEcosmosShop = "ecosmos_shop"
|
||||||
|
)
|
||||||
|
|
||||||
|
var dbs = make(map[string]*gorm.DB)
|
||||||
|
var queryS = make(map[string]*query.Query)
|
||||||
|
|
||||||
|
func Init(cfg *commonConfig.MysqlConfig) error {
|
||||||
|
db, err := initOneDB(cfg, DBNameEcosmosShop)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
queryS[DBNameEcosmosShop] = query.Use(db)
|
||||||
|
|
||||||
|
db, err = initOneDB(cfg, DBNameEcosmos)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
query.SetDefault(db)
|
||||||
|
queryS[DBNameEcosmos] = query.Q
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initOneDB(cfg *commonConfig.MysqlConfig, dbName string) (*gorm.DB, error) {
|
||||||
|
dialect := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", cfg.User, cfg.Password, cfg.Host, cfg.Port, dbName)
|
||||||
|
db, err := gorm.Open(
|
||||||
|
mysql.New(
|
||||||
|
mysql.Config{
|
||||||
|
DSN: dialect,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
&gorm.Config{
|
||||||
|
TranslateError: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sqlDb, err := db.DB()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sqlDb.SetMaxOpenConns(50)
|
||||||
|
sqlDb.SetMaxIdleConns(5)
|
||||||
|
sqlDb.SetConnMaxLifetime(time.Second * 10)
|
||||||
|
if err = sqlDb.Ping(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dbs[dbName] = db
|
||||||
|
return db.Debug(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DBQuery(dbName string) *query.Query {
|
||||||
|
if q, ok := queryS[dbName]; ok {
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Errorf("mysql db not init: %v", dbName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Close() error {
|
||||||
|
fmt.Println("close mysql connect")
|
||||||
|
for _, db := range dbs {
|
||||||
|
sqlDb, err := db.DB()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = sqlDb.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
24
Server/common/db/mysql/sql_code/const.go
Normal file
24
Server/common/db/mysql/sql_code/const.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package sql_code
|
||||||
|
|
||||||
|
const (
|
||||||
|
Unread_HasRead = 1
|
||||||
|
Unread_NotRead = 0
|
||||||
|
IsAgree_Agree = 1
|
||||||
|
IsAgree_Refuse = -1
|
||||||
|
IsAgree_NoDeal = 0
|
||||||
|
Online = 1
|
||||||
|
Offline = 0
|
||||||
|
Mail_UN_READ = 0
|
||||||
|
|
||||||
|
MAIL_UN_READ = 0
|
||||||
|
|
||||||
|
MAIL_READ_NOT_GET = 1
|
||||||
|
|
||||||
|
MAIL_READ_HAS_GET = 2
|
||||||
|
|
||||||
|
MAIL_HAS_DELETE = 3
|
||||||
|
|
||||||
|
MAIL_NO_EXTRAL = 0
|
||||||
|
|
||||||
|
MAIL_HAS_EXTRAL = 1
|
||||||
|
)
|
||||||
57
Server/common/db/redis/redisV9.go
Normal file
57
Server/common/db/redis/redisV9.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
commonConfig "common/config"
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
redisClient *redis.Client
|
||||||
|
redisNotInitErr = errors.New("redis is not initialized.")
|
||||||
|
keyNotExist = errors.New("key does not exist")
|
||||||
|
Nil = redis.Nil
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(cfg *commonConfig.RedisConfig) error {
|
||||||
|
url := fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)
|
||||||
|
if cfg.Tls {
|
||||||
|
redisClient = redis.NewClient(&redis.Options{
|
||||||
|
Addr: url,
|
||||||
|
Password: cfg.Auth,
|
||||||
|
DB: cfg.Db,
|
||||||
|
DialTimeout: 20 * time.Second,
|
||||||
|
Username: cfg.UserName,
|
||||||
|
TLSConfig: &tls.Config{},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
redisClient = redis.NewClient(&redis.Options{
|
||||||
|
Addr: url,
|
||||||
|
Password: cfg.Auth,
|
||||||
|
DB: cfg.Db,
|
||||||
|
DialTimeout: 20 * time.Second,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := redisClient.Ping(context.Background())
|
||||||
|
//p := redisClient.Pipeline()
|
||||||
|
//l := p.HGetAll(xxx, xxx)
|
||||||
|
//s := p.Get(xxx, xx)
|
||||||
|
//p.Exec(xxx)
|
||||||
|
return ret.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Close() error {
|
||||||
|
if redisClient != nil {
|
||||||
|
return redisClient.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRedisClient() *redis.Client {
|
||||||
|
return redisClient
|
||||||
|
}
|
||||||
37
Server/common/db/redis/redis_lock.go
Normal file
37
Server/common/db/redis/redis_lock.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/log"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ReleaseLockExpire = errors.New("release redis lock expire key")
|
||||||
|
|
||||||
|
func Acquire(ctx context.Context, key string, tag string, expiration time.Duration) (bool, error) {
|
||||||
|
success, err := redisClient.SetNX(ctx, key, tag, expiration).Result()
|
||||||
|
return success, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Release(ctx context.Context, key string, tag string) error {
|
||||||
|
script := `
|
||||||
|
if redis.call("GET", KEYS[1]) == ARGV[1] then
|
||||||
|
return redis.call("DEL", KEYS[1])
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end`
|
||||||
|
|
||||||
|
// 执行 Lua 脚本
|
||||||
|
result, err := redisClient.Eval(ctx, script, []string{key}, tag).Result()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// 检查返回值
|
||||||
|
if result == int64(0) {
|
||||||
|
log.Errorf("release redis lock expire key :%v", key)
|
||||||
|
return ReleaseLockExpire
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
49
Server/common/db/test_db.go
Normal file
49
Server/common/db/test_db.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/config"
|
||||||
|
"common/db/mongo"
|
||||||
|
"common/db/mysql"
|
||||||
|
"common/log"
|
||||||
|
"common/utils"
|
||||||
|
"fmt"
|
||||||
|
"github.com/jinzhu/configor"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 用于单元测试初始化数据库
|
||||||
|
|
||||||
|
func InitTestDB(env string) {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("无法获取工作目录:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var commonCfg config.CommonConfig
|
||||||
|
err = configor.Load(&commonCfg, fmt.Sprintf(wd+"/config/common-config-%v.json", env))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Init(&commonCfg.Logger)
|
||||||
|
utils.InitSnowflake(int64(rand.Intn(1000)))
|
||||||
|
//// Redis
|
||||||
|
//if err := redis.Init(&commonCfg.Redis); err != nil {
|
||||||
|
// panic(err)
|
||||||
|
//}
|
||||||
|
// MySQL
|
||||||
|
if err := mysql.Init(&commonCfg.MysqlConfig); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// Mongo
|
||||||
|
if err := mongo.Init(&commonCfg.MongoConfig); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
//// Etcd
|
||||||
|
//if err := etcd.Init(&commonCfg.Etcd); err != nil {
|
||||||
|
// panic(err)
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
||||||
25
Server/common/discover/common/define.go
Normal file
25
Server/common/discover/common/define.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
type ListenerType int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ListenerTypeNewServer = 1 // 服务启动
|
||||||
|
ListenerTypeCloseServer = 2 // 服务关闭
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
KeyDiscover = "discover"
|
||||||
|
KeyDiscoverService = KeyDiscover + "/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
KeyDiscoverGateway = KeyDiscoverService + "/gateway"
|
||||||
|
KeyDiscoverDatabase = KeyDiscoverService + "/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServiceProvider 服务提供者
|
||||||
|
type ServiceProvider struct {
|
||||||
|
Target string
|
||||||
|
SID string
|
||||||
|
Addr string
|
||||||
|
}
|
||||||
28
Server/common/discover/common/tool.go
Normal file
28
Server/common/discover/common/tool.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/db/etcd"
|
||||||
|
"common/log"
|
||||||
|
"context"
|
||||||
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewLeaseAndKeepAlive(ttl int64) (clientv3.LeaseID, error) {
|
||||||
|
lease, err := etcd.Client().Grant(context.Background(), ttl)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
chKeepAlive, err := etcd.Client().KeepAlive(context.Background(), lease.ID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
for r := range chKeepAlive {
|
||||||
|
if r == nil {
|
||||||
|
log.Errorf("lease timeout!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return lease.ID, nil
|
||||||
|
}
|
||||||
41
Server/common/discover/grpc_client/conn.go
Normal file
41
Server/common/discover/grpc_client/conn.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package grpc_client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/log"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/keepalive"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GrpcConnection struct {
|
||||||
|
sid string
|
||||||
|
conn *grpc.ClientConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGrpcConnection(sid, address string) (*GrpcConnection, error) {
|
||||||
|
p := &GrpcConnection{
|
||||||
|
sid: sid,
|
||||||
|
}
|
||||||
|
conn, err := grpc.Dial(
|
||||||
|
address,
|
||||||
|
grpc.WithInsecure(),
|
||||||
|
grpc.WithKeepaliveParams(
|
||||||
|
keepalive.ClientParameters{
|
||||||
|
Time: 30 * time.Second, // 保活探测包发送的时间间隔
|
||||||
|
Timeout: 10 * time.Second, // 保活探测包的超时时间
|
||||||
|
PermitWithoutStream: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
//grpc.WithStatsHandler(&StatsHandler{}),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("create grpc err: %v, sid: %v, addr: %v", err, sid, address)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.conn = conn
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GrpcConnection) GetConnection() *grpc.ClientConn {
|
||||||
|
return g.conn
|
||||||
|
}
|
||||||
62
Server/common/discover/grpc_client/conn_mgr.go
Normal file
62
Server/common/discover/grpc_client/conn_mgr.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package grpc_client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/log"
|
||||||
|
"fmt"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GrpcConnectionMgr struct {
|
||||||
|
poolM map[string]*GrpcConnection
|
||||||
|
poolS []*GrpcConnection
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGrpcConnectionMgr() *GrpcConnectionMgr {
|
||||||
|
return &GrpcConnectionMgr{
|
||||||
|
poolM: make(map[string]*GrpcConnection),
|
||||||
|
poolS: make([]*GrpcConnection, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GrpcConnectionMgr) Store(sid, addr string) {
|
||||||
|
pool, err := NewGrpcConnection(sid, addr)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("create grpc err: %v, sid: %v, addr: %v", err, sid, addr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.poolM[sid] = pool
|
||||||
|
p.poolS = append(p.poolS, pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GrpcConnectionMgr) Delete(sid string) int {
|
||||||
|
delete(p.poolM, sid)
|
||||||
|
for i, pool := range p.poolS {
|
||||||
|
if pool.sid == sid {
|
||||||
|
p.poolS = append(p.poolS[:i], p.poolS[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(p.poolS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GrpcConnectionMgr) Load(sid ...string) (*grpc.ClientConn, error) {
|
||||||
|
var pool *GrpcConnection
|
||||||
|
if len(sid) > 0 && len(sid[0]) > 0 {
|
||||||
|
pool = p.poolM[sid[0]]
|
||||||
|
} else {
|
||||||
|
pool = p.poolS[rand.Intn(len(p.poolS))]
|
||||||
|
}
|
||||||
|
if pool == nil {
|
||||||
|
return nil, fmt.Errorf("cannot find connection")
|
||||||
|
}
|
||||||
|
return pool.GetConnection(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GrpcConnectionMgr) LoadAll() map[string]*grpc.ClientConn {
|
||||||
|
sidM := make(map[string]*grpc.ClientConn)
|
||||||
|
for sid, pool := range p.poolM {
|
||||||
|
sidM[sid] = pool.GetConnection()
|
||||||
|
}
|
||||||
|
return sidM
|
||||||
|
}
|
||||||
45
Server/common/discover/grpc_client/stats.go
Normal file
45
Server/common/discover/grpc_client/stats.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package grpc_client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"google.golang.org/grpc/stats"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 1. 实现 stats.Handler 接口
|
||||||
|
type StatsHandler struct{}
|
||||||
|
|
||||||
|
func (h *StatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
|
||||||
|
// 给 RPC 调用打标签(例如记录方法名)
|
||||||
|
return context.WithValue(ctx, "rpc_method", info.FullMethodName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *StatsHandler) HandleRPC(ctx context.Context, s stats.RPCStats) {
|
||||||
|
// 处理 RPC 统计信息
|
||||||
|
switch t := s.(type) {
|
||||||
|
case *stats.Begin:
|
||||||
|
fmt.Printf("RPC started: %s\n", ctx.Value("rpc_method"))
|
||||||
|
case *stats.End:
|
||||||
|
fmt.Printf("RPC finished: %s (duration: %v)\n",
|
||||||
|
ctx.Value("rpc_method"), t.EndTime.Sub(t.BeginTime))
|
||||||
|
case *stats.InPayload:
|
||||||
|
fmt.Printf("Received %d bytes\n", t.WireLength)
|
||||||
|
case *stats.OutPayload:
|
||||||
|
fmt.Printf("Sent %d bytes\n", t.WireLength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *StatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context {
|
||||||
|
// 给连接打标签
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *StatsHandler) HandleConn(ctx context.Context, s stats.ConnStats) {
|
||||||
|
// 处理连接事件
|
||||||
|
switch s.(type) {
|
||||||
|
case *stats.ConnBegin:
|
||||||
|
fmt.Println("Connection established")
|
||||||
|
case *stats.ConnEnd:
|
||||||
|
fmt.Println("Connection closed")
|
||||||
|
}
|
||||||
|
}
|
||||||
92
Server/common/discover/listener.go
Normal file
92
Server/common/discover/listener.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package discover
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/db/etcd"
|
||||||
|
"common/discover/common"
|
||||||
|
"context"
|
||||||
|
"go.etcd.io/etcd/api/v3/mvccpb"
|
||||||
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
wg = &sync.WaitGroup{}
|
||||||
|
listenerMU = &sync.RWMutex{}
|
||||||
|
listener = make(map[common.ListenerType][]func(data any))
|
||||||
|
stopFunc context.CancelFunc
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterListener 注册服务变动监听
|
||||||
|
func RegisterListener(t common.ListenerType, cb func(data any)) {
|
||||||
|
listenerMU.Lock()
|
||||||
|
defer listenerMU.Unlock()
|
||||||
|
arr := listener[t]
|
||||||
|
if arr == nil {
|
||||||
|
arr = make([]func(data any), 0)
|
||||||
|
}
|
||||||
|
arr = append(arr, cb)
|
||||||
|
listener[t] = arr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据类型触发回调
|
||||||
|
func onCBByType(t common.ListenerType, data any) {
|
||||||
|
listenerMU.RLock()
|
||||||
|
defer listenerMU.RUnlock()
|
||||||
|
for _, f := range listener[t] {
|
||||||
|
f(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Listen() {
|
||||||
|
var stopCtx context.Context
|
||||||
|
stopCtx, stopFunc = context.WithCancel(context.Background())
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
// 服务
|
||||||
|
serviceAll, _ := etcd.Client().Get(stopCtx, common.KeyDiscoverService, clientv3.WithPrefix())
|
||||||
|
for _, kv := range serviceAll.Kvs {
|
||||||
|
onServerChange(clientv3.EventTypePut, string(kv.Key), string(kv.Value))
|
||||||
|
}
|
||||||
|
chService := etcd.Client().Watch(stopCtx, common.KeyDiscoverService, clientv3.WithPrefix(), clientv3.WithRev(serviceAll.Header.Revision+1))
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case msg := <-chService:
|
||||||
|
for _, event := range msg.Events {
|
||||||
|
onServerChange(event.Type, string(event.Kv.Key), string(event.Kv.Value))
|
||||||
|
}
|
||||||
|
case <-stopCtx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 服务发生变化
|
||||||
|
func onServerChange(t mvccpb.Event_EventType, key, value string) {
|
||||||
|
split := strings.Split(key, "/")
|
||||||
|
if len(split) != 5 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch t {
|
||||||
|
case clientv3.EventTypePut:
|
||||||
|
onCBByType(common.ListenerTypeNewServer, &common.ServiceProvider{
|
||||||
|
Target: common.KeyDiscoverService + "/" + split[2],
|
||||||
|
SID: split[3],
|
||||||
|
Addr: value,
|
||||||
|
})
|
||||||
|
case clientv3.EventTypeDelete:
|
||||||
|
onCBByType(common.ListenerTypeCloseServer, &common.ServiceProvider{
|
||||||
|
Target: common.KeyDiscoverService + "/" + split[2],
|
||||||
|
SID: split[3],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Close() {
|
||||||
|
if stopFunc != nil {
|
||||||
|
stopFunc()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
101
Server/common/discover/server.go
Normal file
101
Server/common/discover/server.go
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package discover
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/db/etcd"
|
||||||
|
"common/discover/common"
|
||||||
|
"common/discover/grpc_client"
|
||||||
|
"common/log"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
clientv3 "go.etcd.io/etcd/client/v3"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 大量读少量写的情况下,读写锁比同步Map更高效
|
||||||
|
var (
|
||||||
|
serverMU = sync.RWMutex{}
|
||||||
|
conn = make(map[string]*grpc_client.GrpcConnectionMgr)
|
||||||
|
serverLeaseM = make(map[string]clientv3.LeaseID)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RegisterListener(common.ListenerTypeNewServer, onServerStart)
|
||||||
|
RegisterListener(common.ListenerTypeCloseServer, onServerStop)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindServer 根据SID或随机查找服务
|
||||||
|
func FindServer(target string, sid ...string) (*grpc.ClientConn, error) {
|
||||||
|
serverMU.RLock()
|
||||||
|
defer serverMU.RUnlock()
|
||||||
|
if v, ok := conn[target]; ok {
|
||||||
|
return v.Load(sid...)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("cannot find server")
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindServerAll(target string) map[string]*grpc.ClientConn {
|
||||||
|
serverMU.RLock()
|
||||||
|
defer serverMU.RUnlock()
|
||||||
|
if v, ok := conn[target]; ok {
|
||||||
|
return v.LoadAll()
|
||||||
|
}
|
||||||
|
return make(map[string]*grpc.ClientConn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterGrpcServer 注册服务提供者
|
||||||
|
func RegisterGrpcServer(target, sid, addr string, ttl int64) error {
|
||||||
|
serverMU.Lock()
|
||||||
|
defer serverMU.Unlock()
|
||||||
|
leaseID, err := common.NewLeaseAndKeepAlive(ttl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = etcd.Client().Put(context.Background(), target+"/"+sid, addr, clientv3.WithLease(leaseID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
serverLeaseM[sid] = leaseID
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnRegisterGrpcServer 解注册服务提供者
|
||||||
|
func UnRegisterGrpcServer(sid string) {
|
||||||
|
serverMU.Lock()
|
||||||
|
defer serverMU.Unlock()
|
||||||
|
if leaseID, ok := serverLeaseM[sid]; ok {
|
||||||
|
_, err := etcd.Client().Revoke(context.Background(), leaseID)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("server.go UnRegisterGrpcServer err: %v", err)
|
||||||
|
}
|
||||||
|
delete(serverLeaseM, sid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 某个服务启动了
|
||||||
|
func onServerStart(data any) {
|
||||||
|
if provider, ok := data.(*common.ServiceProvider); ok {
|
||||||
|
serverMU.Lock()
|
||||||
|
defer serverMU.Unlock()
|
||||||
|
if v, ok := conn[provider.Target]; ok {
|
||||||
|
v.Store(provider.SID, provider.Addr)
|
||||||
|
} else {
|
||||||
|
mgr := grpc_client.NewGrpcConnectionMgr()
|
||||||
|
mgr.Store(provider.SID, provider.Addr)
|
||||||
|
conn[provider.Target] = mgr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 某个服务关闭了
|
||||||
|
func onServerStop(data any) {
|
||||||
|
if provider, ok := data.(*common.ServiceProvider); ok {
|
||||||
|
serverMU.Lock()
|
||||||
|
defer serverMU.Unlock()
|
||||||
|
if v, ok := conn[provider.Target]; ok {
|
||||||
|
if v.Delete(provider.SID) == 0 {
|
||||||
|
delete(conn, provider.Target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Server/common/discover/service/client_gateway.go
Normal file
24
Server/common/discover/service/client_gateway.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/discover"
|
||||||
|
"common/discover/common"
|
||||||
|
"common/discover/service/game/game_pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GatewayNewClient(sid ...string) (game_pb.GameClient, error) {
|
||||||
|
c, err := discover.FindServer(common.KeyDiscoverGateway, sid...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return game_pb.NewGameClient(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GatewayNewBroadcastClient() map[string]game_pb.GameClient {
|
||||||
|
clientM := make(map[string]game_pb.GameClient)
|
||||||
|
connM := discover.FindServerAll(common.KeyDiscoverGateway)
|
||||||
|
for sid, conn := range connM {
|
||||||
|
clientM[sid] = game_pb.NewGameClient(conn)
|
||||||
|
}
|
||||||
|
return clientM
|
||||||
|
}
|
||||||
94
Server/common/discover/service/service.go
Normal file
94
Server/common/discover/service/service.go
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"common/discover"
|
||||||
|
"common/discover/common"
|
||||||
|
"common/log"
|
||||||
|
"common/utils"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/keepalive"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IService interface {
|
||||||
|
Init(addr string)
|
||||||
|
Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceBase struct {
|
||||||
|
Target string
|
||||||
|
SID string
|
||||||
|
Serve *grpc.Server
|
||||||
|
EtcdTTL int64
|
||||||
|
OnInit func(serve *grpc.Server)
|
||||||
|
OnClose func()
|
||||||
|
|
||||||
|
wg *sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServiceBase) Init(addr string) {
|
||||||
|
s.wg = &sync.WaitGroup{}
|
||||||
|
s.wg.Add(1)
|
||||||
|
s.SID = utils.SnowflakeInstance().Generate().String()
|
||||||
|
go func() {
|
||||||
|
defer s.wg.Done()
|
||||||
|
defer s.OnClose()
|
||||||
|
defer discover.UnRegisterGrpcServer(s.SID)
|
||||||
|
|
||||||
|
pMin, _ := strconv.ParseInt(os.Getenv("P_MIN"), 10, 64)
|
||||||
|
pMax, _ := strconv.ParseInt(os.Getenv("P_MAX"), 10, 64)
|
||||||
|
if pMin == 0 || pMax == 0 || pMin > pMax {
|
||||||
|
log.Errorf(" %v init err: pMin or pMax is 0 or pMin > pMax", s.Target)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 服务注册
|
||||||
|
lis, port, err := common.ListenRandomPort(pMin, pMax)
|
||||||
|
if lis == nil {
|
||||||
|
log.Errorf(" %v ListenRandomPort err: %v", s.Target, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Serve = grpc.NewServer(
|
||||||
|
grpc.UnaryInterceptor(
|
||||||
|
func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
log.Errorf("server Panic: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resp, err = handler(ctx, req)
|
||||||
|
return
|
||||||
|
},
|
||||||
|
),
|
||||||
|
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
|
||||||
|
MinTime: 20 * time.Second,
|
||||||
|
PermitWithoutStream: true,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
s.OnInit(s.Serve)
|
||||||
|
|
||||||
|
// 服务注册
|
||||||
|
if err = discover.RegisterGrpcServer(s.Target, s.SID, fmt.Sprintf("%v:%d", addr, port), s.EtcdTTL); err != nil {
|
||||||
|
log.Errorf("%v RegisterGrpcServer err: %v", s.Target, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = s.Serve.Serve(lis); err != nil {
|
||||||
|
log.Errorf(" %v Serve err: %v", s.Target, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Infof("%v server stop.", s.Target)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServiceBase) Close() {
|
||||||
|
if s.Serve != nil {
|
||||||
|
s.Serve.Stop()
|
||||||
|
s.wg.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Server/common/go.mod
Normal file
52
Server/common/go.mod
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
module common
|
||||||
|
|
||||||
|
go 1.23.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/getsentry/sentry-go v0.34.0
|
||||||
|
github.com/jinzhu/configor v1.2.2
|
||||||
|
github.com/natefinch/lumberjack v2.0.0+incompatible
|
||||||
|
github.com/redis/go-redis/v9 v9.10.0
|
||||||
|
go.etcd.io/etcd/api/v3 v3.6.1
|
||||||
|
go.etcd.io/etcd/client/v3 v3.6.1
|
||||||
|
go.mongodb.org/mongo-driver v1.17.4
|
||||||
|
go.uber.org/zap v1.27.0
|
||||||
|
google.golang.org/grpc v1.71.1
|
||||||
|
google.golang.org/protobuf v1.36.5
|
||||||
|
gorm.io/driver/mysql v1.6.0
|
||||||
|
gorm.io/gorm v1.30.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
|
github.com/BurntSushi/toml v1.2.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/coreos/go-semver v0.3.1 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||||
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
|
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
|
github.com/xdg-go/scram v1.1.2 // indirect
|
||||||
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.6.1 // indirect
|
||||||
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
golang.org/x/crypto v0.36.0 // indirect
|
||||||
|
golang.org/x/net v0.38.0 // indirect
|
||||||
|
golang.org/x/sync v0.15.0 // indirect
|
||||||
|
golang.org/x/sys v0.31.0 // indirect
|
||||||
|
golang.org/x/text v0.23.0 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
178
Server/common/go.sum
Normal file
178
Server/common/go.sum
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
|
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
|
||||||
|
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||||
|
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||||
|
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
|
||||||
|
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/getsentry/sentry-go v0.34.0 h1:1FCHBVp8TfSc8L10zqSwXUZNiOSF+10qw4czjarTiY4=
|
||||||
|
github.com/getsentry/sentry-go v0.34.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE=
|
||||||
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
|
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||||
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||||
|
github.com/jinzhu/configor v1.2.2 h1:sLgh6KMzpCmaQB4e+9Fu/29VErtBUqsS2t8C9BNIVsA=
|
||||||
|
github.com/jinzhu/configor v1.2.2/go.mod h1:iFFSfOBKP3kC2Dku0ZGB3t3aulfQgTGJknodhFavsU8=
|
||||||
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||||
|
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||||
|
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
|
||||||
|
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
|
||||||
|
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||||
|
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs=
|
||||||
|
github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
|
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||||
|
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||||
|
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||||
|
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||||
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
go.etcd.io/etcd/api/v3 v3.6.1 h1:yJ9WlDih9HT457QPuHt/TH/XtsdN2tubyxyQHSHPsEo=
|
||||||
|
go.etcd.io/etcd/api/v3 v3.6.1/go.mod h1:lnfuqoGsXMlZdTJlact3IB56o3bWp1DIlXPIGKRArto=
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.6.1 h1:CxDVv8ggphmamrXM4Of8aCC8QHzDM4tGcVr9p2BSoGk=
|
||||||
|
go.etcd.io/etcd/client/pkg/v3 v3.6.1/go.mod h1:aTkCp+6ixcVTZmrJGa7/Mc5nMNs59PEgBbq+HCmWyMc=
|
||||||
|
go.etcd.io/etcd/client/v3 v3.6.1 h1:KelkcizJGsskUXlsxjVrSmINvMMga0VWwFF0tSPGEP0=
|
||||||
|
go.etcd.io/etcd/client/v3 v3.6.1/go.mod h1:fCbPUdjWNLfx1A6ATo9syUmFVxqHH9bCnPLBZmnLmMY=
|
||||||
|
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
||||||
|
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||||
|
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||||
|
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||||
|
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||||
|
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||||
|
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||||
|
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||||
|
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||||
|
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
|
||||||
|
google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||||
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
|
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg=
|
||||||
|
gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo=
|
||||||
|
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
|
||||||
|
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
23
Server/common/log/level.go
Normal file
23
Server/common/log/level.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
)
|
||||||
|
|
||||||
|
var logLevelMap = map[string]zapcore.Level{
|
||||||
|
"panic": zap.DPanicLevel,
|
||||||
|
"fatal": zap.FatalLevel,
|
||||||
|
"error": zap.ErrorLevel,
|
||||||
|
"warn": zap.WarnLevel,
|
||||||
|
"info": zap.InfoLevel,
|
||||||
|
"debug": zap.DebugLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLogLevel get the logLevel from logLevelName
|
||||||
|
func GetLogLevel(logLevelName string) zapcore.Level {
|
||||||
|
if v, ok := logLevelMap[logLevelName]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return zap.DebugLevel
|
||||||
|
}
|
||||||
66
Server/common/log/log.go
Normal file
66
Server/common/log/log.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import "go.uber.org/zap"
|
||||||
|
|
||||||
|
var globalLogger *zap.SugaredLogger
|
||||||
|
|
||||||
|
// SetLogger 设置日志记录器
|
||||||
|
func SetLogger(logger *zap.SugaredLogger) {
|
||||||
|
if logger == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
globalLogger = logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLogger() *zap.SugaredLogger {
|
||||||
|
return globalLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf 打印调试模板日志
|
||||||
|
func Debugf(format string, a ...interface{}) {
|
||||||
|
if globalLogger != nil {
|
||||||
|
globalLogger.Debugf(format, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof 打印信息模板日志
|
||||||
|
func Infof(format string, a ...interface{}) {
|
||||||
|
if globalLogger != nil {
|
||||||
|
globalLogger.Infof(format, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf 打印警告模板日志
|
||||||
|
func Warnf(format string, a ...interface{}) {
|
||||||
|
if globalLogger != nil {
|
||||||
|
globalLogger.Warnf(format, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf 打印错误模板日志
|
||||||
|
func Errorf(format string, a ...interface{}) {
|
||||||
|
if globalLogger != nil {
|
||||||
|
globalLogger.Errorf(format, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panicf 打印Panic模板日志
|
||||||
|
func Panicf(format string, a ...interface{}) {
|
||||||
|
if globalLogger != nil {
|
||||||
|
globalLogger.Panicf(format, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf 打印致命错误模板日志
|
||||||
|
func Fatalf(format string, a ...interface{}) {
|
||||||
|
if globalLogger != nil {
|
||||||
|
globalLogger.Fatalf(format, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close 关闭日志
|
||||||
|
func Close() {
|
||||||
|
if globalLogger != nil {
|
||||||
|
_ = globalLogger.Sync()
|
||||||
|
}
|
||||||
|
}
|
||||||
62
Server/common/log/log_zap.go
Normal file
62
Server/common/log/log_zap.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
commonConfig "common/config"
|
||||||
|
"github.com/natefinch/lumberjack"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(cfg *commonConfig.LoggerConfig) {
|
||||||
|
// 格式配置
|
||||||
|
jsonConfig := zapcore.EncoderConfig{
|
||||||
|
MessageKey: "M",
|
||||||
|
LevelKey: "L",
|
||||||
|
TimeKey: "T",
|
||||||
|
NameKey: "N",
|
||||||
|
CallerKey: "C",
|
||||||
|
FunctionKey: zapcore.OmitKey,
|
||||||
|
StacktraceKey: "S",
|
||||||
|
LineEnding: zapcore.DefaultLineEnding,
|
||||||
|
EncodeLevel: zapcore.CapitalLevelEncoder,
|
||||||
|
EncodeTime: zapcore.TimeEncoderOfLayout("01-02 15:04:05.000"),
|
||||||
|
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||||
|
EncodeCaller: zapcore.ShortCallerEncoder,
|
||||||
|
EncodeName: nil,
|
||||||
|
ConsoleSeparator: " ",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日志输出到控制台和文件
|
||||||
|
writeSyncer := []zapcore.WriteSyncer{zapcore.AddSync(os.Stdout)}
|
||||||
|
if !cfg.Debug {
|
||||||
|
writeSyncer = append(writeSyncer, zapcore.AddSync(&lumberjack.Logger{
|
||||||
|
Filename: "./logs/log.log", // 日志文件位置
|
||||||
|
MaxSize: cfg.MaxSize, // 最大文件大小(MB)
|
||||||
|
MaxBackups: cfg.MaxBackUp, // 保留旧文件的最大个数
|
||||||
|
MaxAge: cfg.MaxAge, // 保留旧文件的最大天数
|
||||||
|
Compress: false, // 是否压缩/归档旧文件
|
||||||
|
LocalTime: true,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
var encoder zapcore.Encoder
|
||||||
|
if cfg.Debug {
|
||||||
|
encoder = zapcore.NewConsoleEncoder(jsonConfig)
|
||||||
|
} else {
|
||||||
|
encoder = zapcore.NewJSONEncoder(jsonConfig)
|
||||||
|
}
|
||||||
|
logger := zap.New(zapcore.NewCore(
|
||||||
|
encoder,
|
||||||
|
zapcore.NewMultiWriteSyncer(writeSyncer...),
|
||||||
|
zap.NewAtomicLevelAt(GetLogLevel(cfg.Level)),
|
||||||
|
))
|
||||||
|
if cfg.Debug {
|
||||||
|
logger = logger.WithOptions(
|
||||||
|
zap.AddCaller(),
|
||||||
|
zap.AddCallerSkip(1),
|
||||||
|
zap.AddStacktrace(zapcore.WarnLevel),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SetLogger(logger.Sugar())
|
||||||
|
}
|
||||||
135
Server/common/log/sentry.go
Normal file
135
Server/common/log/sentry.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
import "github.com/getsentry/sentry-go"
|
||||||
|
|
||||||
|
type SentryCoreConfig struct {
|
||||||
|
Tags map[string]string
|
||||||
|
AttachStacktrace bool
|
||||||
|
Level zapcore.Level
|
||||||
|
FlushTimeout time.Duration
|
||||||
|
Hub *sentry.Hub
|
||||||
|
Platform string
|
||||||
|
}
|
||||||
|
|
||||||
|
type sentryCore struct {
|
||||||
|
zapcore.LevelEnabler
|
||||||
|
client sentry.Client
|
||||||
|
cfg SentryCoreConfig
|
||||||
|
flushTimeout time.Duration
|
||||||
|
fields map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sentryCore) with(fs []zapcore.Field) *sentryCore {
|
||||||
|
m := make(map[string]interface{}, len(c.fields))
|
||||||
|
for k, v := range c.fields {
|
||||||
|
m[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
enc := zapcore.NewMapObjectEncoder()
|
||||||
|
for _, f := range fs {
|
||||||
|
f.AddTo(enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range enc.Fields {
|
||||||
|
m[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sentryCore{
|
||||||
|
client: c.client,
|
||||||
|
cfg: c.cfg,
|
||||||
|
fields: m,
|
||||||
|
LevelEnabler: c.LevelEnabler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sentryCore) With(fs []zapcore.Field) zapcore.Core {
|
||||||
|
return c.with(fs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sentryCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
|
||||||
|
if c.cfg.Level.Enabled(ent.Level) {
|
||||||
|
return ce.AddCore(ent, c)
|
||||||
|
}
|
||||||
|
return ce
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sentryCore) Write(ent zapcore.Entry, fs []zapcore.Field) error {
|
||||||
|
clone := c.with(fs)
|
||||||
|
event := sentry.NewEvent()
|
||||||
|
event.Message = ent.Message
|
||||||
|
event.Timestamp = ent.Time
|
||||||
|
event.Level = sentryLevel(ent.Level)
|
||||||
|
event.Platform = c.cfg.Platform
|
||||||
|
event.Extra = clone.fields
|
||||||
|
event.Tags = c.cfg.Tags
|
||||||
|
|
||||||
|
if c.cfg.AttachStacktrace {
|
||||||
|
trace := sentry.NewStacktrace()
|
||||||
|
if trace != nil {
|
||||||
|
event.Exception = []sentry.Exception{
|
||||||
|
{
|
||||||
|
Type: ent.Message,
|
||||||
|
Value: ent.Caller.TrimmedPath(),
|
||||||
|
Stacktrace: trace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hub := c.cfg.Hub
|
||||||
|
if hub == nil {
|
||||||
|
hub = sentry.CurrentHub()
|
||||||
|
}
|
||||||
|
_ = c.client.CaptureEvent(event, nil, hub.Scope())
|
||||||
|
|
||||||
|
if ent.Level > zapcore.ErrorLevel {
|
||||||
|
c.client.Flush(c.flushTimeout)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *sentryCore) Sync() error {
|
||||||
|
c.client.Flush(c.flushTimeout)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSentryCore(cfg SentryCoreConfig, sentryClient *sentry.Client) zapcore.Core {
|
||||||
|
core := sentryCore{
|
||||||
|
client: *sentryClient,
|
||||||
|
cfg: cfg,
|
||||||
|
LevelEnabler: cfg.Level,
|
||||||
|
flushTimeout: 3 * time.Second,
|
||||||
|
fields: make(map[string]interface{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.FlushTimeout > 0 {
|
||||||
|
core.flushTimeout = cfg.FlushTimeout
|
||||||
|
}
|
||||||
|
|
||||||
|
return &core
|
||||||
|
}
|
||||||
|
|
||||||
|
func sentryLevel(lvl zapcore.Level) sentry.Level {
|
||||||
|
switch lvl {
|
||||||
|
case zapcore.DebugLevel:
|
||||||
|
return sentry.LevelDebug
|
||||||
|
case zapcore.InfoLevel:
|
||||||
|
return sentry.LevelInfo
|
||||||
|
case zapcore.WarnLevel:
|
||||||
|
return sentry.LevelWarning
|
||||||
|
case zapcore.ErrorLevel:
|
||||||
|
return sentry.LevelError
|
||||||
|
case zapcore.DPanicLevel:
|
||||||
|
return sentry.LevelFatal
|
||||||
|
case zapcore.PanicLevel:
|
||||||
|
return sentry.LevelFatal
|
||||||
|
case zapcore.FatalLevel:
|
||||||
|
return sentry.LevelFatal
|
||||||
|
default:
|
||||||
|
return sentry.LevelFatal
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user