Apply .gitignore rules

This commit is contained in:
皮蛋13361098506
2025-01-06 16:21:36 +08:00
parent 1b77f62820
commit ccd2c530cf
580 changed files with 69806 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
package securityUtil
import (
"fmt"
"testing"
)
var (
ExpectedUpperString = "5EB63BBBE01EEED093CB22BB8F5ACDC3"
ExpectedLowerString = "5eb63bbbe01eeed093cb22bb8f5acdc3"
)
func TestMd5String(t *testing.T) {
s := fmt.Sprintf("&GroupId=%s&ClusterId=%s&IP=%s&ServiceName=%s&ServiceId=%s&Timestamp=%d&GroupSecret=%s",
"DSN", "DSN_AREA1", "10.255.0.226", "gs1", "4fa2b870-f8eb-4a47-a4bb-becf14f3b628", 1649212351304327500, "88F5BC56-96D3-4021-A358-BBDAFFBF772A")
//s := "hello world"
result := Md5String(s, true)
if result != ExpectedUpperString {
t.Errorf("Md5String(\"hello world\") failed.Got %s, expected %s", result, ExpectedUpperString)
}
result = Md5String(s, false)
if result != ExpectedLowerString {
t.Errorf("Md5String(\"hello world\") failed.Got %s, expected %s", result, ExpectedLowerString)
}
}
func TestMd5Bytes(t *testing.T) {
s := "hello world"
b := []byte(s)
result := Md5Bytes(b, true)
if result != ExpectedUpperString {
t.Errorf("Md5String(\"hello world\") failed.Got %s, expected %s", result, ExpectedUpperString)
}
result = Md5Bytes(b, false)
if result != ExpectedLowerString {
t.Errorf("Md5String(\"hello world\") failed.Got %s, expected %s", result, ExpectedLowerString)
}
}

View File

@@ -0,0 +1,111 @@
package ensureSendUtil
import (
"fmt"
"time"
"goutil/debugUtil"
"goutil/logUtil"
)
// 负责发送数据的协程
func sendLoop(s sender, closeSignal chan struct{}) {
defer func() {
if r := recover(); r != nil {
logUtil.LogUnknownError(r)
}
}()
for {
select {
case <-s.Done():
closeSignal <- struct{}{}
return
case v := <-s.Data():
if err := s.Send(v); err != nil {
// 发送失败存入缓存
s.Cache() <- v
}
}
}
}
// 定时重发失败的数据
func resendLoop(s sender, folder string, closeSignal chan struct{}) {
defer func() {
if r := recover(); r != nil {
logUtil.LogUnknownError(r)
}
}()
// debug模式每秒重试1次
var delay time.Duration
if debugUtil.IsDebug() {
delay = time.Second
} else {
delay = time.Minute * 5
}
// 定时重发失败数据
for {
select {
case <-s.Done():
closeSignal <- struct{}{}
return
case <-time.After(delay):
sendCacheData(s, folder)
loadData(s.(EnsureSender), folder)
}
}
}
// 从sender获取失败数据重发
func sendCacheData(s sender, folder string) {
failed := make([]dataItem, 0)
length := len(s.Cache())
defer func() {
// 用于记录多次失败后放弃发送的数据
giveUpItems := make(chan dataItem, len(failed))
for _, v := range failed {
if v.Count() >= 3 {
// 失败次数太多的数据准备存放到磁盘中
giveUpItems <- v
} else {
s.Cache() <- v
}
}
giveUpLen := len(giveUpItems)
if giveUpLen > 0 {
// 将多次失败的数据保存到文件中
if folder[len(folder)-1] == '/' {
folder = folder[:len(folder)-1]
}
saveData(giveUpItems, folder+"_giveup")
if giveUpLen >= 5 {
log := fmt.Sprintf("ensureSendUtil: 有%d条数据多次发送失败", giveUpLen)
logUtil.NormalLog(log, logUtil.Error)
}
}
// 输出信息
log := fmt.Sprintf("ensureSendUtil: 重发%d条数据失败%d条存盘%d条\n", length, len(failed), giveUpLen)
logUtil.NormalLog(log, logUtil.Info)
}()
for {
select {
case v := <-s.Cache():
// 重发数据
if e := s.Send(v); e != nil {
// 记录失败的数据
failed = append(failed, v)
}
default:
return
}
}
}

View File

@@ -0,0 +1,162 @@
package webServer
import (
"Framework/ipMgr"
"goutil/debugUtil"
"goutil/typeUtil"
)
// 参数传输类型
type ParamTransferType string
const (
// 以Form表单形式来传递参数
Con_Form ParamTransferType = "Form"
// 以二进制流形式来传递参数
Con_Stream ParamTransferType = "Stream"
)
type handlerFunc func(*Context)
// 请求处理配置对象
type HandlerConfig struct {
// 是否需要验证IP
IsCheckIP bool
// 参数类型
ParamTransferType ParamTransferType
// 方法参数名称集合
ParamNameList []string
// 非空参数名称集合
NotEmptyParamNameList []string
}
// 请求处理对象
type handler struct {
// 用户自定义数据(注册回调时设置通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
userData interface{}
// 注册的访问路径
path string
// 方法定义
funcObj handlerFunc
// 请求处理配置对象
configObj *HandlerConfig
// 正则表达式
regex bool
}
// 检查IP是否合法
func (this *handler) checkIP(context *Context, ifCheckIPWhenDebug bool) bool {
if this.configObj == nil {
return true
}
if this.configObj.IsCheckIP == false {
return true
}
if debugUtil.IsDebug() == true && ifCheckIPWhenDebug == false {
return true
}
if ipMgr.IsIpValid(context.GetRequestIP()) {
return true
}
return false
}
// 检测参数
func (this *handler) checkParam(context *Context, methodName string, paramCheckHandler func(paramMap typeUtil.MapData, paramNameList []string, notEmptyParamList []string) ([]string, []string, bool)) (missParamList []string, emptyParamList []string, valid bool) {
valid = true
if this.configObj == nil {
return
}
// 获取方法的参数集合
var dataMap typeUtil.MapData
switch this.configObj.ParamTransferType {
case Con_Stream:
data := new(map[string]interface{})
if exist, err := context.Unmarshal(data); err != nil || !exist {
valid = false
return
}
dataMap = typeUtil.NewMapData(*data)
default:
if methodName == "POST" {
dataMap = context.GetPostFormValueData()
} else {
dataMap = context.GetFormValueData()
}
}
// 定义默认的参数验证方法
defaultParamCheckHandler := func(paramMap typeUtil.MapData, paramNameList []string, notEmptyParamList []string) (_missParamList []string, _emptyParamList []string, _valid bool) {
_valid = true
// 遍历判断每一个参数是否存在;为了搜集所有的参数,所以不会提前返回
for _, name := range paramNameList {
if _, exist := paramMap[name]; !exist {
_missParamList = append(_missParamList, name)
_valid = false
}
}
for _, name := range notEmptyParamList {
if value, _ := paramMap[name]; value == "" {
_emptyParamList = append(_emptyParamList, name)
_valid = false
}
}
return
}
// 如果没有指定验证参数的方法,就使用默认方法
if paramCheckHandler == nil {
missParamList, emptyParamList, valid = defaultParamCheckHandler(dataMap, this.configObj.ParamNameList, this.configObj.NotEmptyParamNameList)
} else {
missParamList, emptyParamList, valid = paramCheckHandler(dataMap, this.configObj.ParamNameList, this.configObj.NotEmptyParamNameList)
}
return
}
// 检测POST参数
func (this *handler) checkPostParam(context *Context) bool {
if this.configObj == nil {
return true
}
for _, name := range this.configObj.ParamNameList {
if _, exist := context.GetPostFormValueData()[name]; !exist {
return false
}
}
for _, name := range this.configObj.NotEmptyParamNameList {
if value, _ := context.GetPostFormValueData()[name]; value == "" {
return false
}
}
return true
}
// 创建新的请求方法对象
func newHandler(path string, funcObj handlerFunc, configObj *HandlerConfig) *handler {
return &handler{
path: path,
funcObj: funcObj,
configObj: configObj,
regex: false,
}
}

View File

@@ -0,0 +1,178 @@
/*
通过在RWLocker对象中引入writeProtectEndTime写锁保护结束时间来提高获取写锁的成功率。
当写锁获取失败时,就设置一个写锁保护结束时间,在这段时间内,只允许写锁进行获取,而读锁的获取请求会被拒绝。
通过重置写锁保护结束时间的时机,对写锁的优先级程度进行调整。有两个重置写锁保护结束时间的时机:
1、在成功获取到写锁时:此时重置,有利于下一个写锁需求者在当前写锁持有者处理逻辑时设置保护时间,从而当当前写锁持有者释放锁时,下一个写锁需求者可以立刻获得写锁;
2、在写锁解锁时:此时重置,给了读锁和写锁的需求者同样的机会进行锁的竞争机会;
综上RWLocker可以提供中级别的写锁优先级
1、高级:在获取写锁失败时设置写锁保护结束时间;在获取写锁成功时重置。
2、中级:在获取写锁失败时设置写锁保护结束时间;在释放锁时重置。
3、无:不设置写锁保护时间。
*/
package syncUtil
import (
"fmt"
"runtime/debug"
"sync"
"time"
)
// 读写锁对象
type RWLocker struct {
read int
write int // 使用int而不是bool值的原因是为了与read保持类型的一致
writeProtectEndTime int64 // 写锁保护结束时间。如果当前时间小于该值,则会阻塞读锁请求;以便于提高写锁的优先级,避免连续的读锁导致写锁无法获得;
prevStack []byte
mutex sync.Mutex
}
// 尝试加写锁
// 返回值:加写锁是否成功
func (this *RWLocker) lock() bool {
this.mutex.Lock()
defer this.mutex.Unlock()
// 如果已经被锁定,则返回失败;并且设置写锁保护结束时间;以便于写锁可以优先竞争锁;
if this.write == 1 || this.read > 0 {
this.writeProtectEndTime = time.Now().UnixNano() + con_Write_Protect_Nanoseconds
return false
}
// 否则,将写锁数量设置为1,并返回成功;并重置写锁保护结束时间;这样读锁和写锁都可以参与锁的竞争;
this.write = 1
this.writeProtectEndTime = time.Now().UnixNano()
// 记录Stack信息
if if_record_stack_info {
this.prevStack = debug.Stack()
}
return true
}
// 写锁定
// timeout:超时毫秒数,timeout<=0则将会死等
// 返回值:
// 成功或失败
// 如果失败,返回上一次成功加锁时的堆栈信息
// 如果失败,返回当前的堆栈信息
func (this *RWLocker) Lock(timeout int) (successful bool, prevStack string, currStack string) {
timeout = getTimeout(timeout)
// 遍历指定的次数(即指定的超时时间)
for i := 0; i < timeout; i++ {
// 如果锁定成功,则返回成功
if this.lock() {
successful = true
break
}
// 如果锁定失败则休眠1ms然后再重试
time.Sleep(time.Millisecond)
}
// 如果时间结束仍然是失败,则返回上次成功的堆栈信息,以及当前的堆栈信息
if successful == false {
if this.prevStack != nil && len(this.prevStack) > 0 {
prevStack = string(this.prevStack)
}
currStack = string(debug.Stack())
}
return
}
// 写锁定(死等)
func (this *RWLocker) WaitLock() {
successful, prevStack, currStack := this.Lock(0)
if successful == false {
fmt.Printf("RWLocker:WaitLock():{PrevStack:%s, currStack:%s}\n", prevStack, currStack)
}
}
// 释放写锁
func (this *RWLocker) Unlock() {
this.mutex.Lock()
defer this.mutex.Unlock()
this.write = 0
//释放写锁保护时间,避免调时间导致读锁超时
this.writeProtectEndTime = 0
}
// 尝试加读锁
// 返回值:加读锁是否成功
func (this *RWLocker) rlock() bool {
this.mutex.Lock()
defer this.mutex.Unlock()
// 如果已经被锁定,或者处于写锁保护时间段内,则返回失败
if this.write == 1 || time.Now().UnixNano() < this.writeProtectEndTime {
return false
}
// 否则,将读锁数量加1,并返回成功
this.read += 1
// 记录Stack信息
if if_record_stack_info {
this.prevStack = debug.Stack()
}
return true
}
// 读锁定
// timeout:超时毫秒数,timeout<=0则将会死等
// 返回值:
// 成功或失败
// 如果失败,返回上一次成功加锁时的堆栈信息
// 如果失败,返回当前的堆栈信息
func (this *RWLocker) RLock(timeout int) (successful bool, prevStack string, currStack string) {
timeout = getTimeout(timeout)
// 遍历指定的次数(即指定的超时时间)
// 读锁比写锁优先级更低所以每次休眠2ms所以尝试的次数就是时间/2
for i := 0; i < timeout; i++ {
// 如果锁定成功,则返回成功
if this.rlock() {
successful = true
break
}
// 如果锁定失败则休眠1ms然后再重试
time.Sleep(time.Millisecond)
}
// 如果时间结束仍然是失败,则返回上次成功的堆栈信息,以及当前的堆栈信息
if successful == false {
if this.prevStack != nil && len(this.prevStack) > 0 {
prevStack = string(this.prevStack)
}
currStack = string(debug.Stack())
}
return
}
// 读锁定(死等)
func (this *RWLocker) WaitRLock() {
successful, prevStack, currStack := this.RLock(0)
if successful == false {
fmt.Printf("RWLocker:WaitRLock():{PrevStack:%s, currStack:%s}\n", prevStack, currStack)
}
}
// 释放读锁
func (this *RWLocker) RUnlock() {
this.mutex.Lock()
defer this.mutex.Unlock()
if this.read > 0 {
this.read -= 1
}
}
// 创建新的读写锁对象
func NewRWLocker() *RWLocker {
return &RWLocker{}
}

View File

@@ -0,0 +1,67 @@
package printMgr
import (
"fmt"
"sync"
. "Framework/startMgr"
)
var (
funcMap = make(map[string]*FuncItem)
mutex sync.Mutex
)
// 注册方法(如果名称重复会panic)
// name:方法名称(唯一标识)
// moduleType:模块类型
// definition:方法定义
func Register(name string, moduleType ModuleType, definition func() error) {
mutex.Lock()
defer mutex.Unlock()
if _, exists := funcMap[name]; exists {
panic(fmt.Sprintf("%s已经存在请重新命名", name))
}
funcMap[name] = NewFuncItem(name, moduleType, definition)
}
// 调用所有方法
// 返回值:
// 错误列表
func CallAll() (errList []error) {
mutex.Lock()
defer mutex.Unlock()
for _, item := range funcMap {
// 调用方法
if err := item.Call(); err != nil {
errList = append(errList, err)
}
}
return
}
// 按照模块类型进行调用
// moduleType:模块类型
// 返回值:
// errList:错误列表
func CallType(moduleType ModuleType) (errList []error) {
mutex.Lock()
defer mutex.Unlock()
for _, item := range funcMap {
if item.ModuleType != moduleType {
continue
}
// 调用方法
if err := item.Call(); err != nil {
errList = append(errList, err)
}
}
return
}

View File

@@ -0,0 +1,55 @@
package model
import (
"fmt"
)
// 批量删除消息请求对象
type BatchDeleteMessageRequest struct {
// 公共请求参数
common *CommonRequest
// 上次消费消息时返回的消息句柄列表
receiptHandleList []string
}
// 获取请求方法名
func (this *BatchDeleteMessageRequest) GetActionName() string {
return "BatchDeleteMessage"
}
// SetCommonRequestObject 设置公共请求对象
func (this *BatchDeleteMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
this.common = commonRequest
}
// AssembleParamMap 组装参数字典
// 返回值
// map[string]string:请求参数字典
func (this *BatchDeleteMessageRequest) AssembleParamMap() map[string]string {
paramMap := this.common.AssembleParamMap()
for index, msg := range this.receiptHandleList {
key := fmt.Sprintf("receiptHandle.%d", index)
paramMap[key] = msg
}
return paramMap
}
func NewBatchDeleteMessageRequest(receiptHandleList []string) *BatchDeleteMessageRequest {
return &BatchDeleteMessageRequest{
receiptHandleList: receiptHandleList,
}
}
// 批量删除消息请求返回结果对象
type BatchDeleteMessageResponse struct {
*CommonResponse
// 无法成功删除的错误列表
ErrorList []*ErrorInfo `json:"errorList"`
}
func NewBatchDeleteMessageResponse() *BatchDeleteMessageResponse {
return &BatchDeleteMessageResponse{}
}

View File

@@ -0,0 +1,103 @@
package verifyMgr
import (
"fmt"
"sync"
"Framework/managecenterMgr"
"goutil/webUtil"
)
var (
verifyUrlMap = make(map[string]VerifyType)
mutex sync.RWMutex
con_SuccessStatusCode = 200
)
// 初始化需要验证的Url及对应的验证方式
func Init(url string, _type VerifyType) {
mutex.Lock()
defer mutex.Unlock()
if _, exists := verifyUrlMap[url]; exists {
panic(fmt.Errorf("%s已经存在请检查", url))
}
verifyUrlMap[url] = _type
}
// 验证
func Verify() (errList []error) {
errList1 := verifyInternal()
errList2 := verifyServerGroup()
if len(errList1) > 0 {
errList = append(errList, errList1...)
}
if len(errList2) > 0 {
errList = append(errList, errList2...)
}
return
}
// 验证内部的url
func verifyInternal() (errList []error) {
// 验证单独指定的url
mutex.RLock()
defer mutex.RUnlock()
header := webUtil.GetFormHeader()
transport := webUtil.NewTransport()
transport.DisableKeepAlives = true
transport = webUtil.GetTimeoutTransport(transport, 30)
for url, _type := range verifyUrlMap {
switch _type {
case Con_Get:
if statusCode, _, err := webUtil.GetWebData3(url, "", header, transport); statusCode != con_SuccessStatusCode || err != nil {
errList = append(errList, fmt.Errorf("access %s failed. StatusCode:%d, err:%s", url, statusCode, err))
}
case Con_Post:
if statusCode, _, err := webUtil.PostMapData(url, nil, header, transport); statusCode != con_SuccessStatusCode || err != nil {
errList = append(errList, fmt.Errorf("access %s failed. StatusCode:%d, err:%s", url, statusCode, err))
}
default:
errList = append(errList, fmt.Errorf("the type of %s is wrong, not it's %d", url, _type))
}
}
return
}
// 验证服务器组的url
func verifyServerGroup() (errList []error) {
// 验证配置在ManageCenter中的所有ServerGroup
serverGroupList := managecenterMgr.GetServerGroupList()
chList := make([]chan bool, 0, len(serverGroupList))
header := webUtil.GetFormHeader()
transport := webUtil.NewTransport()
transport.DisableKeepAlives = true
transport = webUtil.GetTimeoutTransport(transport, 30)
for _, item := range serverGroupList {
url := item.GetGSCallbackUrl("Verify.ashx")
ch := make(chan bool)
chList = append(chList, ch)
go func(_url string, _ch chan bool) {
fmt.Printf("VerifyUrl:%s\n", _url)
if statusCode, _, err := webUtil.PostMapData(_url, nil, header, transport); statusCode != con_SuccessStatusCode || err != nil {
errList = append(errList, fmt.Errorf("access %s failed. StatusCode:%d, err:%s", _url, statusCode, err))
}
_ch <- true
}(url, ch)
}
// 等待所有的ch返回
for _, ch := range chList {
<-ch
}
return
}

View File

@@ -0,0 +1,101 @@
package ensureSendUtil
import (
"goutil/zlibUtil"
)
type dataItem interface {
// 返回原始数据
String() string
// 返回发送字节流
Bytes() []byte
// 设置发送次数
SetCount(uint)
// 返回发送次数
Count() uint
}
/////////////////////////////////////////////////
// httpDataItem
type httpDataItem struct {
// 数据
data string
// 发送次数
count uint
}
func newHTTPData(_data string) dataItem {
return &httpDataItem{
data: _data,
count: 0,
}
}
// 返回原始数据
func (this *httpDataItem) String() string {
return this.data
}
// 返回原始数据用于发送
func (this *httpDataItem) Bytes() []byte {
return []byte(this.data)
}
func (this *httpDataItem) SetCount(cnt uint) {
this.count = cnt
}
func (this *httpDataItem) Count() uint {
return this.count
}
/////////////////////////////////////////////////
// tcpDataItem
type tcpDataItem struct {
// 原始数据
origin string
// 压缩后数据
data []byte
// 重试次数
count uint
}
func newTCPDataItem(_data string) (dataItem, error) {
compressed, err := zlibUtil.Compress([]byte(_data), 5)
if err != nil {
return nil, err
}
item := &tcpDataItem{
origin: _data,
data: compressed,
count: 0,
}
return item, nil
}
// 返回原始数据
func (this *tcpDataItem) String() string {
return this.origin
}
// 返回压缩数据用于发送
func (this *tcpDataItem) Bytes() []byte {
return this.data
}
func (this *tcpDataItem) SetCount(cnt uint) {
this.count = cnt
}
func (this *tcpDataItem) Count() uint {
return this.count
}