@@ -0,0 +1,262 @@ | |||||
## Ignore Visual Studio temporary files, build results, and | |||||
## files generated by popular Visual Studio add-ons. | |||||
# User-specific files | |||||
*.suo | |||||
*.user | |||||
*.userosscache | |||||
*.sln.docstates | |||||
*.editorconfig | |||||
.vscode | |||||
__commit.bat | |||||
__download.bat | |||||
target | |||||
# User-specific files (MonoDevelop/Xamarin Studio) | |||||
*.userprefs | |||||
# Build results | |||||
[Dd]ebug/ | |||||
[Dd]ebugPublic/ | |||||
[Rr]elease/ | |||||
[Rr]eleases/ | |||||
x64/ | |||||
x86/ | |||||
bld/ | |||||
[Bb]in/ | |||||
[Oo]bj/ | |||||
[Ll]og/ | |||||
# Visual Studio 2015 cache/options directory | |||||
**/.vs/ | |||||
# Uncomment if you have tasks that create the project's static files in wwwroot | |||||
#wwwroot/ | |||||
# MSTest test Results | |||||
[Tt]est[Rr]esult*/ | |||||
[Bb]uild[Ll]og.* | |||||
# NUNIT | |||||
*.VisualState.xml | |||||
TestResult.xml | |||||
# Build Results of an ATL Project | |||||
[Dd]ebugPS/ | |||||
[Rr]eleasePS/ | |||||
dlldata.c | |||||
# DNX | |||||
project.lock.json | |||||
artifacts/ | |||||
*_i.c | |||||
*_p.c | |||||
*_i.h | |||||
*.ilk | |||||
*.meta | |||||
*.obj | |||||
*.pch | |||||
*.pdb | |||||
*.pgc | |||||
*.pgd | |||||
*.rsp | |||||
*.sbr | |||||
*.tlb | |||||
*.tli | |||||
*.tlh | |||||
*.tmp | |||||
*.tmp_proj | |||||
*.log | |||||
*.vspscc | |||||
*.vssscc | |||||
.builds | |||||
*.pidb | |||||
*.svclog | |||||
*.scc | |||||
# Chutzpah Test files | |||||
_Chutzpah* | |||||
# Visual C++ cache files | |||||
ipch/ | |||||
*.aps | |||||
*.ncb | |||||
*.opendb | |||||
*.opensdf | |||||
*.sdf | |||||
*.cachefile | |||||
*.VC.db | |||||
*.VC.VC.opendb | |||||
# Visual Studio profiler | |||||
*.psess | |||||
*.vsp | |||||
*.vspx | |||||
*.sap | |||||
# TFS 2012 Local Workspace | |||||
$tf/ | |||||
# Guidance Automation Toolkit | |||||
*.gpState | |||||
# ReSharper is a .NET coding add-in | |||||
_ReSharper*/ | |||||
*.[Rr]e[Ss]harper | |||||
*.DotSettings.user | |||||
# JustCode is a .NET coding add-in | |||||
.JustCode | |||||
# TeamCity is a build add-in | |||||
_TeamCity* | |||||
# DotCover is a Code Coverage Tool | |||||
*.dotCover | |||||
# NCrunch | |||||
_NCrunch_* | |||||
.*crunch*.local.xml | |||||
nCrunchTemp_* | |||||
# MightyMoose | |||||
*.mm.* | |||||
AutoTest.Net/ | |||||
# Web workbench (sass) | |||||
.sass-cache/ | |||||
# Installshield output folder | |||||
[Ee]xpress/ | |||||
# DocProject is a documentation generator add-in | |||||
DocProject/buildhelp/ | |||||
DocProject/Help/*.HxT | |||||
DocProject/Help/*.HxC | |||||
DocProject/Help/*.hhc | |||||
DocProject/Help/*.hhk | |||||
DocProject/Help/*.hhp | |||||
DocProject/Help/Html2 | |||||
DocProject/Help/html | |||||
# Click-Once directory | |||||
publish/ | |||||
# Publish Web Output | |||||
*.[Pp]ublish.xml | |||||
*.azurePubxml | |||||
# TODO: Comment the next line if you want to checkin your web deploy settings | |||||
# but database connection strings (with potential passwords) will be unencrypted | |||||
*.pubxml | |||||
*.publishproj | |||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to | |||||
# checkin your Azure Web App publish settings, but sensitive information contained | |||||
# in these scripts will be unencrypted | |||||
PublishScripts/ | |||||
# NuGet Packages | |||||
*.nupkg | |||||
*.snupkg | |||||
# The packages folder can be ignored because of Package Restore | |||||
**/packages/* | |||||
# except build/, which is used as an MSBuild target. | |||||
!**/packages/build/ | |||||
# Uncomment if necessary however generally it will be regenerated when needed | |||||
#!**/packages/repositories.config | |||||
# NuGet v3's project.json files produces more ignoreable files | |||||
*.nuget.props | |||||
*.nuget.targets | |||||
# Microsoft Azure Build Output | |||||
csx/ | |||||
*.build.csdef | |||||
# Microsoft Azure Emulator | |||||
ecf/ | |||||
rcf/ | |||||
# Windows Store app package directories and files | |||||
AppPackages/ | |||||
BundleArtifacts/ | |||||
Package.StoreAssociation.xml | |||||
_pkginfo.txt | |||||
# Visual Studio cache files | |||||
# files ending in .cache can be ignored | |||||
*.[Cc]ache | |||||
# but keep track of directories ending in .cache | |||||
!*.[Cc]ache/ | |||||
# Others | |||||
ClientBin/ | |||||
~$* | |||||
*~ | |||||
*.dbmdl | |||||
*.dbproj.schemaview | |||||
*.pfx | |||||
*.publishsettings | |||||
node_modules/ | |||||
orleans.codegen.cs | |||||
# Since there are multiple workflows, uncomment next line to ignore bower_components | |||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | |||||
#bower_components/ | |||||
# RIA/Silverlight projects | |||||
Generated_Code/ | |||||
# Backup & report files from converting an old project file | |||||
# to a newer Visual Studio version. Backup files are not needed, | |||||
# because we have git ;-) | |||||
_UpgradeReport_Files/ | |||||
Backup*/ | |||||
UpgradeLog*.XML | |||||
UpgradeLog*.htm | |||||
# SQL Server files | |||||
*.mdf | |||||
*.ldf | |||||
# Business Intelligence projects | |||||
*.rdl.data | |||||
*.bim.layout | |||||
*.bim_*.settings | |||||
# Microsoft Fakes | |||||
FakesAssemblies/ | |||||
# GhostDoc plugin setting file | |||||
*.GhostDoc.xml | |||||
# Node.js Tools for Visual Studio | |||||
.ntvs_analysis.dat | |||||
# Visual Studio 6 build log | |||||
*.plg | |||||
# Visual Studio 6 workspace options file | |||||
*.opt | |||||
# Visual Studio LightSwitch build output | |||||
**/*.HTMLClient/GeneratedArtifacts | |||||
**/*.DesktopClient/GeneratedArtifacts | |||||
**/*.DesktopClient/ModelManifest.xml | |||||
**/*.Server/GeneratedArtifacts | |||||
**/*.Server/ModelManifest.xml | |||||
_Pvt_Extensions | |||||
# Paket dependency manager | |||||
.paket/paket.exe | |||||
paket-files/ | |||||
# FAKE - F# Make | |||||
.fake/ | |||||
# JetBrains Rider | |||||
.idea/ | |||||
*.sln.iml | |||||
# macOS | |||||
.DS_Store |
@@ -4,47 +4,19 @@ import ( | |||||
"C" | "C" | ||||
"fmt" | "fmt" | ||||
"time" | "time" | ||||
"yitidgen/idgen" | |||||
"yitidgen/regworkerid" | |||||
"github.com/yitter/idgenerator-go/idgen" | |||||
) | ) | ||||
//export SetOptions | |||||
func SetOptions(workerId uint16) { | func SetOptions(workerId uint16) { | ||||
var options = idgen.NewIdGeneratorOptions(workerId) | var options = idgen.NewIdGeneratorOptions(workerId) | ||||
idgen.SetIdGenerator(options) | idgen.SetIdGenerator(options) | ||||
} | } | ||||
//export NextId | |||||
func NextId() int64 { | func NextId() int64 { | ||||
return idgen.NextId() | return idgen.NextId() | ||||
} | } | ||||
// 注册一个 WorkerId,会先注销所有本机已注册的记录 | |||||
//export RegisterOne | |||||
func RegisterOne(ip *C.char, port int32, password *C.char, maxWorkerId int32) int32 { | |||||
return regworkerid.RegisterOne(C.GoString(ip), port, C.GoString(password), maxWorkerId) | |||||
} | |||||
// 注册多个 WorkerId,会先注销所有本机已注册的记录 | |||||
///export RegisterMany | |||||
func RegisterMany(ip *C.char, port int32, password *C.char, maxWorkerId int32, totalCount int32) []int32 { | |||||
//values := regworkerid.RegisterMany(C.GoString(ip), port, C.GoString(password), maxWorkerId, totalCount) | |||||
//return (*C.int)(unsafe.Pointer(&values)) | |||||
return regworkerid.RegisterMany(C.GoString(ip), port, C.GoString(password), maxWorkerId, totalCount) | |||||
} | |||||
// 注销本机已注册的 WorkerId | |||||
//export UnRegister | |||||
func UnRegister() { | |||||
regworkerid.UnRegister() | |||||
} | |||||
// 检查本地WorkerId是否有效(0-有效,其它-无效) | |||||
//export Validate | |||||
func Validate(workerId int32) int32 { | |||||
return regworkerid.Validate(workerId) | |||||
} | |||||
func main() { | func main() { | ||||
const testGenId = true // 测试设置 | const testGenId = true // 测试设置 | ||||
@@ -70,21 +42,36 @@ func main() { | |||||
time.Sleep(time.Duration(1000) * time.Millisecond) | time.Sleep(time.Duration(1000) * time.Millisecond) | ||||
} | } | ||||
} else { | } else { | ||||
workerIdList := regworkerid.RegisterMany("localhost", 6379, "", 4, 3) | |||||
// ip := "localhost" | |||||
ipChar := C.CString("localhost") | |||||
passChar := C.CString("") | |||||
workerIdList := RegisterMany(ipChar, 6379, passChar, 4, 3, 0) | |||||
for _, value := range workerIdList { | for _, value := range workerIdList { | ||||
fmt.Println("注册的WorkerId:", value) | fmt.Println("注册的WorkerId:", value) | ||||
} | } | ||||
//var workerId = regworkerid.RegisterOne("localhost", 6379, "", 4) | |||||
//fmt.Println("注册的WorkerId:", workerId) | |||||
id := RegisterOne(ipChar, 6379, passChar, 4, 0) | |||||
fmt.Println("注册的WorkerId:", id) | |||||
// C.free(unsafe.Pointer(ipChar)) | |||||
// C.free(unsafe.Pointer(passChar)) | |||||
// var workerId = regworkerid.RegisterOne(ip, 6379, "", 4) | |||||
// fmt.Println("注册的WorkerId:", workerId) | |||||
fmt.Println("end") | fmt.Println("end") | ||||
time.Sleep(time.Duration(300) * time.Second) | time.Sleep(time.Duration(300) * time.Second) | ||||
} | } | ||||
} | } | ||||
// To Build a dll/so: | |||||
// windows: | // windows: | ||||
// go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go | |||||
// go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go reg.go | |||||
// linux init: go install -buildmode=shared -linkshared std | // linux init: go install -buildmode=shared -linkshared std | ||||
// go build -o ./target/yitidgengo.so -buildmode=c-shared main.go | |||||
// go build -o ./target/yitidgengo.so -buildmode=c-shared main.go reg.go | |||||
// https://books.studygolang.com/advanced-go-programming-book/ch2-cgo/ch2-09-static-shared-lib.html |
@@ -0,0 +1,32 @@ | |||||
package main | |||||
import ( | |||||
"C" | |||||
) | |||||
import "github.com/yitter/idgenerator-go/regworkerid" | |||||
//export RegisterOne | |||||
// 注册一个 WorkerId,会先注销所有本机已注册的记录 | |||||
func RegisterOne(ip *C.char, port int32, password *C.char, maxWorkerId int32, database int) int32 { | |||||
return regworkerid.RegisterOne(C.GoString(ip), port, C.GoString(password), maxWorkerId, database) | |||||
} | |||||
// RegisterMany | |||||
// 注册多个 WorkerId,会先注销所有本机已注册的记录 | |||||
func RegisterMany(ip *C.char, port int32, password *C.char, maxWorkerId, totalCount int32, database int) []int32 { | |||||
// return (*C.int)(unsafe.Pointer(&values)) | |||||
//return regworkerid.RegisterMany(ip, port, password, maxWorkerId, totalCount, database) | |||||
return regworkerid.RegisterMany(C.GoString(ip), port, C.GoString(password), maxWorkerId, totalCount, database) | |||||
} | |||||
//export UnRegister | |||||
// 注销本机已注册的 WorkerId | |||||
func UnRegister() { | |||||
regworkerid.UnRegister() | |||||
} | |||||
//export Validate | |||||
// 检查本地WorkerId是否有效(0-有效,其它-无效) | |||||
func Validate(workerId int32) int32 { | |||||
return regworkerid.Validate(workerId) | |||||
} |
@@ -3,15 +3,17 @@ | |||||
* 开源地址:https://github.com/yitter/idgenerator | * 开源地址:https://github.com/yitter/idgenerator | ||||
*/ | */ | ||||
// Package regworkerid implements a simple distributed id generator. | |||||
package regworkerid | package regworkerid | ||||
import ( | import ( | ||||
"context" | "context" | ||||
"fmt" | "fmt" | ||||
"github.com/go-redis/redis/v8" | |||||
"strconv" | "strconv" | ||||
"sync" | "sync" | ||||
"time" | "time" | ||||
"github.com/go-redis/redis/v8" | |||||
) | ) | ||||
var _client *redis.Client | var _client *redis.Client | ||||
@@ -27,6 +29,7 @@ var _WorkerIdLifeTimeSeconds = 15 // IdGen:WorkerId:Value:xx 的值在 redis | |||||
var _MaxLoopCount = 10 // 最大循环次数(无可用WorkerId时循环查找) | var _MaxLoopCount = 10 // 最大循环次数(无可用WorkerId时循环查找) | ||||
var _SleepMillisecondEveryLoop = 200 // 每次循环后,暂停时间 | var _SleepMillisecondEveryLoop = 200 // 每次循环后,暂停时间 | ||||
var _MaxWorkerId int32 = 0 // 最大WorkerId值,超过此值从0开始 | var _MaxWorkerId int32 = 0 // 最大WorkerId值,超过此值从0开始 | ||||
var _Database int = 0 // 最大WorkerId值,超过此值从0开始 | |||||
var _RedisConnString = "" | var _RedisConnString = "" | ||||
var _RedisPassword = "" | var _RedisPassword = "" | ||||
@@ -34,8 +37,10 @@ var _RedisPassword = "" | |||||
const _WorkerIdIndexKey string = "IdGen:WorkerId:Index" // redis 中的key | const _WorkerIdIndexKey string = "IdGen:WorkerId:Index" // redis 中的key | ||||
const _WorkerIdValueKeyPrefix string = "IdGen:WorkerId:Value:" // redis 中的key | const _WorkerIdValueKeyPrefix string = "IdGen:WorkerId:Value:" // redis 中的key | ||||
const _WorkerIdFlag = "Y" // IdGen:WorkerId:Value:xx 的值(将来可用 _token 替代) | const _WorkerIdFlag = "Y" // IdGen:WorkerId:Value:xx 的值(将来可用 _token 替代) | ||||
const _Log = false // 是否输出日志 | |||||
const _Log = false // 是否输出日志 | |||||
// export Validate | |||||
// 检查本地WorkerId是否有效(0-有效,其它-无效) | |||||
func Validate(workerId int32) int32 { | func Validate(workerId int32) int32 { | ||||
for _, value := range _workerIdList { | for _, value := range _workerIdList { | ||||
if value == workerId { | if value == workerId { | ||||
@@ -45,13 +50,15 @@ func Validate(workerId int32) int32 { | |||||
return 0 | return 0 | ||||
//if workerId == _usingWorkerId { | |||||
// if workerId == _usingWorkerId { | |||||
// return 0 | // return 0 | ||||
//} else { | |||||
// } else { | |||||
// return -1 | // return -1 | ||||
//} | |||||
// } | |||||
} | } | ||||
// export UnRegister | |||||
// 注销本机已注册的 WorkerId | |||||
func UnRegister() { | func UnRegister() { | ||||
_workerIdLock.Lock() | _workerIdLock.Lock() | ||||
@@ -73,7 +80,7 @@ func autoUnRegister() { | |||||
} | } | ||||
} | } | ||||
func RegisterMany(ip string, port int32, password string, maxWorkerId int32, totalCount int32) []int32 { | |||||
func RegisterMany(ip string, port int32, password string, maxWorkerId int32, totalCount int32, database int) []int32 { | |||||
if maxWorkerId < 0 { | if maxWorkerId < 0 { | ||||
return []int32{-2} | return []int32{-2} | ||||
} | } | ||||
@@ -87,6 +94,7 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot | |||||
_MaxWorkerId = maxWorkerId | _MaxWorkerId = maxWorkerId | ||||
_RedisConnString = ip + ":" + strconv.Itoa(int(port)) | _RedisConnString = ip + ":" + strconv.Itoa(int(port)) | ||||
_RedisPassword = password | _RedisPassword = password | ||||
_Database = database | |||||
_client = newRedisClient() | _client = newRedisClient() | ||||
if _client == nil { | if _client == nil { | ||||
return []int32{-1} | return []int32{-1} | ||||
@@ -96,15 +104,15 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot | |||||
_ = _client.Close() | _ = _client.Close() | ||||
} | } | ||||
}() | }() | ||||
//_, err := _client.Ping(_ctx).Result() | |||||
//if err != nil { | |||||
// _, err := _client.Ping(_ctx).Result() | |||||
// if err != nil { | |||||
// //panic("init redis error") | // //panic("init redis error") | ||||
// return []int{-3} | // return []int{-3} | ||||
//} else { | |||||
// } else { | |||||
// if _Log { | // if _Log { | ||||
// fmt.Println("init redis ok") | // fmt.Println("init redis ok") | ||||
// } | // } | ||||
//} | |||||
// } | |||||
_lifeIndex++ | _lifeIndex++ | ||||
_workerIdList = make([]int32, totalCount) | _workerIdList = make([]int32, totalCount) | ||||
@@ -117,7 +125,7 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot | |||||
id := register(_lifeIndex) | id := register(_lifeIndex) | ||||
if id > -1 { | if id > -1 { | ||||
useExtendFunc = true | useExtendFunc = true | ||||
_workerIdList[key] = id //= append(_workerIdList, id) | |||||
_workerIdList[key] = id // = append(_workerIdList, id) | |||||
} else { | } else { | ||||
break | break | ||||
} | } | ||||
@@ -130,7 +138,9 @@ func RegisterMany(ip string, port int32, password string, maxWorkerId int32, tot | |||||
return _workerIdList | return _workerIdList | ||||
} | } | ||||
func RegisterOne(ip string, port int32, password string, maxWorkerId int32) int32 { | |||||
// export RegisterOne | |||||
// 注册一个 WorkerId,会先注销所有本机已注册的记录 | |||||
func RegisterOne(ip string, port int32, password string, maxWorkerId int32, database int) int32 { | |||||
if maxWorkerId < 0 { | if maxWorkerId < 0 { | ||||
return -2 | return -2 | ||||
} | } | ||||
@@ -141,6 +151,7 @@ func RegisterOne(ip string, port int32, password string, maxWorkerId int32) int3 | |||||
_RedisConnString = ip + ":" + strconv.Itoa(int(port)) | _RedisConnString = ip + ":" + strconv.Itoa(int(port)) | ||||
_RedisPassword = password | _RedisPassword = password | ||||
_loopCount = 0 | _loopCount = 0 | ||||
_Database = database | |||||
_client = newRedisClient() | _client = newRedisClient() | ||||
if _client == nil { | if _client == nil { | ||||
return -3 | return -3 | ||||
@@ -150,15 +161,15 @@ func RegisterOne(ip string, port int32, password string, maxWorkerId int32) int3 | |||||
_ = _client.Close() | _ = _client.Close() | ||||
} | } | ||||
}() | }() | ||||
//_, err := _client.Ping(_ctx).Result() | |||||
//if err != nil { | |||||
// _, err := _client.Ping(_ctx).Result() | |||||
// if err != nil { | |||||
// // panic("init redis error") | // // panic("init redis error") | ||||
// return -3 | // return -3 | ||||
//} else { | |||||
// } else { | |||||
// if _Log { | // if _Log { | ||||
// fmt.Println("init redis ok") | // fmt.Println("init redis ok") | ||||
// } | // } | ||||
//} | |||||
// } | |||||
_lifeIndex++ | _lifeIndex++ | ||||
var id = register(_lifeIndex) | var id = register(_lifeIndex) | ||||
@@ -179,11 +190,11 @@ func newRedisClient() *redis.Client { | |||||
return redis.NewClient(&redis.Options{ | return redis.NewClient(&redis.Options{ | ||||
Addr: _RedisConnString, | Addr: _RedisConnString, | ||||
Password: _RedisPassword, | Password: _RedisPassword, | ||||
DB: 0, | |||||
//PoolSize: 1000, | |||||
//ReadTimeout: time.Millisecond * time.Duration(100), | |||||
//WriteTimeout: time.Millisecond * time.Duration(100), | |||||
//IdleTimeout: time.Second * time.Duration(60), | |||||
DB: _Database, | |||||
// PoolSize: 1000, | |||||
// ReadTimeout: time.Millisecond * time.Duration(100), | |||||
// WriteTimeout: time.Millisecond * time.Duration(100), | |||||
// IdleTimeout: time.Second * time.Duration(60), | |||||
}) | }) | ||||
} | } | ||||
@@ -310,9 +321,9 @@ func extendWorkerIdLifeTime(lifeIndex int, workerId int32) { | |||||
} | } | ||||
// 已经被注销,则终止(此步是上一步的二次验证) | // 已经被注销,则终止(此步是上一步的二次验证) | ||||
//if _usingWorkerId < 0 { | |||||
// if _usingWorkerId < 0 { | |||||
// break | // break | ||||
//} | |||||
// } | |||||
// 延长 redis 数据有效期 | // 延长 redis 数据有效期 | ||||
extendWorkerIdFlag(myWorkerId) | extendWorkerIdFlag(myWorkerId) | ||||