From 88fc34776da19ce244aaf26ce9e5dd538f407362 Mon Sep 17 00:00:00 2001 From: keepchen Date: Thu, 28 Dec 2023 13:26:34 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=96=B0=E5=A2=9Eetcd=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AF,2.=E6=96=B0=E5=A2=9E=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E8=A7=A3=E6=9E=90=E6=96=B9=E6=B3=95,3.=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 +++++---- README_EN.md | 15 +++++---- go.mod | 22 ++++++++----- go.sum | 40 ++++++++++++++++++------ lib/etcd/conf.go | 11 +++++++ lib/etcd/etcdv3.go | 65 +++++++++++++++++++++++++++++++++++++++ lib/etcd/watch.go | 27 ++++++++++++++++ lib/kafka/conf.go | 2 +- sail/components.go | 7 +++++ sail/config/config.go | 9 ++++++ sail/config/utils.go | 27 ++++++++++++++++ sail/config/utils_test.go | 47 +++++++++++++++++++++++++++- sail/sail.go | 25 +++++++++------ schedule/schedule.go | 6 ++-- 14 files changed, 276 insertions(+), 42 deletions(-) create mode 100644 lib/etcd/conf.go create mode 100644 lib/etcd/etcdv3.go create mode 100644 lib/etcd/watch.go diff --git a/README.md b/README.md index e8bd094..28e8cfb 100644 --- a/README.md +++ b/README.md @@ -76,23 +76,26 @@ import ( "github.com/keepchen/go-sail/v3/sail" ) -//日志组件 +//获取日志组件 sail.GetLogger() -//数据库连接(读、写实例) +//获取数据库连接(读、写实例) sail.GetDB() -//redis连接(单例模式) +//获取redis连接(单例模式) sail.GetRedis() -//redis连接(cluster模式) +//获取redis连接(cluster模式) sail.GetRedisCluster() -//nats连接 +//获取nats连接 sail.GetNats() -//kafka完整连接实例 +//获取kafka完整连接实例 sail.GetKafkaInstance() + +//获取etcd连接实例 +sail.GetEtcdInstance() ``` 更多组件持续开发中,也欢迎大家提PR👏🏻👏🏻 diff --git a/README_EN.md b/README_EN.md index a7556b6..9dfe052 100644 --- a/README_EN.md +++ b/README_EN.md @@ -76,23 +76,26 @@ import ( "github.com/keepchen/go-sail/v3/sail" ) -//日志组件 +//获取日志组件 sail.GetLogger() -//数据库连接(读、写实例) +//获取数据库连接(读、写实例) sail.GetDB() -//redis连接(单例模式) +//获取redis连接(单例模式) sail.GetRedis() -//redis连接(cluster模式) +//获取redis连接(cluster模式) sail.GetRedisCluster() -//nats连接 +//获取nats连接 sail.GetNats() -//kafka完整连接实例 +//获取kafka完整连接实例 sail.GetKafkaInstance() + +//获取etcd连接实例 +sail.GetEtcdInstance() ``` PR is welcome👏🏻👏🏻 diff --git a/go.mod b/go.mod index 157c783..8107671 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/go-redis/redis/v8 v8.11.5 github.com/golang-jwt/jwt v3.2.2+incompatible - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/jinzhu/configor v1.2.1 github.com/nacos-group/nacos-sdk-go/v2 v2.1.2 github.com/nats-io/nats.go v1.26.0 @@ -22,6 +22,7 @@ require ( github.com/swaggo/gin-swagger v1.5.3 github.com/swaggo/swag v1.8.8 github.com/tjfoc/gmsm v1.4.1 + go.etcd.io/etcd/client/v3 v3.5.11 go.uber.org/zap v1.24.0 golang.org/x/net v0.17.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 @@ -46,8 +47,10 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect @@ -63,10 +66,11 @@ require ( github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect @@ -110,20 +114,24 @@ require ( 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 + go.etcd.io/etcd/api/v3 v3.5.11 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.11 // indirect go.opentelemetry.io/otel v1.10.0 // indirect go.opentelemetry.io/otel/trace v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect golang.org/x/arch v0.3.0 // indirect golang.org/x/crypto v0.14.0 // indirect - golang.org/x/sync v0.1.0 // indirect + golang.org/x/sync v0.3.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.6.0 // indirect - google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect - google.golang.org/grpc v1.48.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 2172391..1dff4c6 100644 --- a/go.sum +++ b/go.sum @@ -81,8 +81,9 @@ github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZX github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= @@ -99,8 +100,12 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -184,9 +189,11 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= @@ -226,8 +233,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -240,8 +248,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -255,8 +263,9 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -561,6 +570,12 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.etcd.io/etcd/api/v3 v3.5.11 h1:B54KwXbWDHyD3XYAwprxNzTe7vlhR69LuBgZnMVvS7E= +go.etcd.io/etcd/api/v3 v3.5.11/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= +go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A= +go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= +go.etcd.io/etcd/client/v3 v3.5.11 h1:ajWtgoNSZJ1gmS8k+icvPtqsqEav+iUorF7b0qozgUU= +go.etcd.io/etcd/client/v3 v3.5.11/go.mod h1:a6xQUEqFJ8vztO1agJh/KQKOMfFI8og52ZconzcDJwE= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -724,8 +739,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -933,8 +949,13 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -949,8 +970,9 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -965,8 +987,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/lib/etcd/conf.go b/lib/etcd/conf.go new file mode 100644 index 0000000..45033dc --- /dev/null +++ b/lib/etcd/conf.go @@ -0,0 +1,11 @@ +package etcd + +import "crypto/tls" + +type Conf struct { + Endpoints []string `yaml:"endpoints" toml:"endpoints" json:"endpoints"` //地址列表,如: localhost:2379 + Username string `yaml:"username" toml:"username" json:"username"` //账号 + Password string `yaml:"password" toml:"password" json:"password"` //密码 + Timeout int `yaml:"timeout" toml:"timeout" json:"timeout"` //连接超时时间(毫秒)默认10000ms + Tls *tls.Config `yaml:"-" toml:"-" json:"-"` //tls配置 +} diff --git a/lib/etcd/etcdv3.go b/lib/etcd/etcdv3.go new file mode 100644 index 0000000..43b0e57 --- /dev/null +++ b/lib/etcd/etcdv3.go @@ -0,0 +1,65 @@ +//@doc https://github.com/etcd-io/etcd/tree/main/client/v3 + +package etcd + +import ( + "time" + + clientv3 "go.etcd.io/etcd/client/v3" +) + +var client *clientv3.Client + +// Init 初始化连接实例 +func Init(conf Conf) { + if conf.Timeout == 0 { + conf.Timeout = 10000 + } + + cfg := clientv3.Config{ + Endpoints: conf.Endpoints, + DialTimeout: time.Duration(conf.Timeout) * time.Millisecond, + } + + if conf.Tls != nil { + cfg.TLS = conf.Tls + } + if len(conf.Username) != 0 && len(conf.Password) != 0 { + cfg.Username = conf.Username + cfg.Password = conf.Password + } + + cli, err := clientv3.New(cfg) + if err != nil { + panic(err) + } + + client = cli +} + +// GetInstance 获取连接实例 +func GetInstance() *clientv3.Client { + return client +} + +// New 新建连接实例 +func New(conf Conf) (*clientv3.Client, error) { + if conf.Timeout == 0 { + conf.Timeout = 10000 + } + + cfg := clientv3.Config{ + Endpoints: conf.Endpoints, + DialTimeout: time.Duration(conf.Timeout) * time.Millisecond, + } + + if conf.Tls != nil { + cfg.TLS = conf.Tls + } + if len(conf.Username) != 0 && len(conf.Password) != 0 { + cfg.Username = conf.Username + cfg.Password = conf.Password + } + + return clientv3.New(cfg) +} diff --git a/lib/etcd/watch.go b/lib/etcd/watch.go new file mode 100644 index 0000000..c93f2bb --- /dev/null +++ b/lib/etcd/watch.go @@ -0,0 +1,27 @@ +package etcd + +import ( + "context" + + clientv3 "go.etcd.io/etcd/client/v3" +) + +// Watch 监听key +func Watch(key string, fn func(k, v []byte)) { + watchChan := GetInstance().Watch(context.Background(), key) + for watchResp := range watchChan { + for _, value := range watchResp.Events { + fn(value.Kv.Key, value.Kv.Value) + } + } +} + +// WatchWithPrefix 监听key,带前缀 +func WatchWithPrefix(key string, fn func(k, v []byte)) { + watchChan := GetInstance().Watch(context.Background(), key, clientv3.WithPrefix()) + for watchResp := range watchChan { + for _, value := range watchResp.Events { + fn(value.Kv.Key, value.Kv.Value) + } + } +} diff --git a/lib/kafka/conf.go b/lib/kafka/conf.go index d81e4ef..db5cca2 100644 --- a/lib/kafka/conf.go +++ b/lib/kafka/conf.go @@ -8,5 +8,5 @@ type Conf struct { Username string `yaml:"username" toml:"username" json:"username"` //账号 Password string `yaml:"password" toml:"password" json:"password"` //密码 Timeout int `yaml:"timeout" toml:"timeout" json:"timeout"` //连接超时时间(毫秒)默认10000ms - Tls *tls.Config //tls配置 + Tls *tls.Config `yaml:"-" toml:"-" json:"-"` //tls配置//tls配置 } diff --git a/sail/components.go b/sail/components.go index 797a8d0..69bb514 100644 --- a/sail/components.go +++ b/sail/components.go @@ -5,12 +5,14 @@ import ( redisLib "github.com/go-redis/redis/v8" "github.com/keepchen/go-sail/v3/http/api" "github.com/keepchen/go-sail/v3/lib/db" + "github.com/keepchen/go-sail/v3/lib/etcd" "github.com/keepchen/go-sail/v3/lib/kafka" "github.com/keepchen/go-sail/v3/lib/logger" "github.com/keepchen/go-sail/v3/lib/nats" "github.com/keepchen/go-sail/v3/lib/redis" natsLib "github.com/nats-io/nats.go" kafkaLib "github.com/segmentio/kafka-go" + clientv3 "go.etcd.io/etcd/client/v3" "go.uber.org/zap" "gorm.io/gorm" ) @@ -82,3 +84,8 @@ func GetKafkaWriter() *kafkaLib.Writer { func GetKafkaReader() *kafkaLib.Reader { return kafka.GetReader() } + +// GetEtcdInstance 获取etcd连接实例 +func GetEtcdInstance() *clientv3.Client { + return etcd.GetInstance() +} diff --git a/sail/config/config.go b/sail/config/config.go index 2afd5ed..571b47a 100644 --- a/sail/config/config.go +++ b/sail/config/config.go @@ -3,6 +3,7 @@ package config import ( "github.com/keepchen/go-sail/v3/lib/db" "github.com/keepchen/go-sail/v3/lib/email" + "github.com/keepchen/go-sail/v3/lib/etcd" "github.com/keepchen/go-sail/v3/lib/jwt" "github.com/keepchen/go-sail/v3/lib/kafka" "github.com/keepchen/go-sail/v3/lib/logger" @@ -21,6 +22,7 @@ type Config struct { JwtConf jwt.Conf `yaml:"jwt_conf" toml:"jwt_conf" json:"jwt_conf"` //jwt配置 EmailConf email.Conf `yaml:"email_conf" toml:"email_conf" json:"email_conf"` //邮件配置 KafkaConf KafkaExtraConf `yaml:"kafka_conf" toml:"kafka_conf" json:"kafka_conf"` //kafka配置 + EtcdConf etcd.Conf `yaml:"etcd_conf" toml:"etcd_conf" json:"etcd_conf"` //etcd配置 } // HttpServerConf http服务配置 @@ -49,3 +51,10 @@ type KafkaExtraConf struct { Topic string `yaml:"topic" toml:"topic" json:"topic"` //主题 GroupID string `yaml:"groupID" toml:"groupID" json:"groupID"` //分组id } + +var config *Config + +// Get 获取配置 +func Get() *Config { + return config +} diff --git a/sail/config/utils.go b/sail/config/utils.go index 83bb5f6..5c1e1dd 100644 --- a/sail/config/utils.go +++ b/sail/config/utils.go @@ -48,3 +48,30 @@ func PrintTemplateConfig(format string, writeToFile ...string) { fmt.Println(string(configStr)) } } + +// ParseConfigFromBytes 从字符串解析配置 +// +// @param format 内容格式,支持: json|yaml|toml +// +// @param writeToFile 写入到目标文件(可选) +func ParseConfigFromBytes(format string, source []byte) (*Config, error) { + var ( + formatList = [...]string{"json", "yaml", "toml"} + conf Config + err error + ) + + switch format { + case formatList[0]: + err = json.Unmarshal(source, &conf) + case formatList[1]: + err = yaml.Unmarshal(source, &conf) + case formatList[2]: + err = toml.Unmarshal(source, &conf) + default: + fmt.Printf("[GO-SAIL] dump config by using unknown format: %s\n", format) + err = fmt.Errorf("[GO-SAIL] dump config by using unknown format: %s\n", format) + } + + return &conf, err +} diff --git a/sail/config/utils_test.go b/sail/config/utils_test.go index d9a4220..6918aa8 100644 --- a/sail/config/utils_test.go +++ b/sail/config/utils_test.go @@ -1,6 +1,15 @@ package config -import "testing" +import ( + "encoding/json" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v2" + + "github.com/keepchen/go-sail/v3/lib/etcd" +) func TestPrintConfig(t *testing.T) { formats := [...]string{"json", "toml", "yaml", "unknown"} @@ -9,3 +18,39 @@ func TestPrintConfig(t *testing.T) { } t.Log("OK") } + +func TestParseConfigFromString(t *testing.T) { + formats := [...]string{"json", "toml", "yaml", "unknown"} + conf := &Config{ + HttpServer: HttpServerConf{ + Debug: true, + Addr: ":8000", + }, + EtcdConf: etcd.Conf{ + Timeout: 10, + }, + } + js, jsErr := json.Marshal(conf) + assert.NoError(t, jsErr) + c1, c1Err := ParseConfigFromBytes(formats[0], js) + assert.NoError(t, c1Err) + assert.Equal(t, true, c1.HttpServer.Debug) + assert.Equal(t, ":8000", c1.HttpServer.Addr) + assert.Equal(t, 10, c1.EtcdConf.Timeout) + + tml, tmlErr := toml.Marshal(conf) + assert.NoError(t, tmlErr) + c2, c2Err := ParseConfigFromBytes(formats[1], tml) + assert.NoError(t, c2Err) + assert.Equal(t, true, c2.HttpServer.Debug) + assert.Equal(t, ":8000", c2.HttpServer.Addr) + assert.Equal(t, 10, c2.EtcdConf.Timeout) + + ym, ymErr := yaml.Marshal(conf) + assert.NoError(t, ymErr) + c3, c3Err := ParseConfigFromBytes(formats[2], ym) + assert.NoError(t, c3Err) + assert.Equal(t, true, c3.HttpServer.Debug) + assert.Equal(t, ":8000", c3.HttpServer.Addr) + assert.Equal(t, 10, c3.EtcdConf.Timeout) +} diff --git a/sail/sail.go b/sail/sail.go index 42ad75c..adc349f 100644 --- a/sail/sail.go +++ b/sail/sail.go @@ -3,6 +3,8 @@ package sail import ( "sync" + "github.com/keepchen/go-sail/v3/lib/etcd" + "github.com/keepchen/go-sail/v3/lib/kafka" "github.com/keepchen/go-sail/v3/sail/config" @@ -57,8 +59,8 @@ func (f *Framework) Launch(registerRoutes func(ginEngine *gin.Engine), before, a wg := &sync.WaitGroup{} - //:: 根据配置一次初始化组件、启动服务 :: - //- before + //:: 根据配置依次初始化组件、启动服务 :: + //- before,自定义前置函数调用 if before != nil { before() } @@ -67,35 +69,40 @@ func (f *Framework) Launch(registerRoutes func(ginEngine *gin.Engine), before, a logger.Init(f.conf.LoggerConf, f.appName) //- redis(standalone) - if len(f.conf.RedisConf.Host) != 0 { + if len(f.conf.RedisConf.Host) > 0 { redis.InitRedis(f.conf.RedisConf) } //- redis(cluster) - if len(f.conf.RedisClusterConf.AddrList) != 0 { + if len(f.conf.RedisClusterConf.AddrList) > 0 { redis.InitRedisCluster(f.conf.RedisClusterConf) } //- database - if len(f.conf.DBConf.DriverName) != 0 { + if len(f.conf.DBConf.DriverName) > 0 { db.Init(f.conf.DBConf) } //- jwt - if len(f.conf.JwtConf.PublicKey) != 0 { + if len(f.conf.JwtConf.PublicKey) > 0 { f.conf.JwtConf.Load() } //- nats - if len(f.conf.NatsConf.Servers) != 0 { + if len(f.conf.NatsConf.Servers) > 0 { nats.Init(f.conf.NatsConf) } //- kafka - if len(f.conf.KafkaConf.Conf.AddrList) != 0 { + if len(f.conf.KafkaConf.Conf.AddrList) > 0 { kafka.Init(f.conf.KafkaConf.Conf, f.conf.KafkaConf.Topic, f.conf.KafkaConf.GroupID) } + //- etcd + if len(f.conf.EtcdConf.Endpoints) > 0 { + etcd.Init(f.conf.EtcdConf) + } + //- gin ginEngine := httpserver.InitGinEngine(f.conf.HttpServer) @@ -119,7 +126,7 @@ func (f *Framework) Launch(registerRoutes func(ginEngine *gin.Engine), before, a printSummaryInfo(f.conf.HttpServer, ginEngine) - //- after + //- after,自定义后置函数调用 if after != nil { after() } diff --git a/schedule/schedule.go b/schedule/schedule.go index 6cf87c6..a92209d 100644 --- a/schedule/schedule.go +++ b/schedule/schedule.go @@ -43,7 +43,7 @@ func Job(name string, task func()) *TaskJob { go func() { job.cancelTaskChan <- struct{}{} close(job.cancelTaskChan) - fmt.Printf("[go-sail] task schedule cancel job {%s} successfully\n", job.name) + fmt.Printf("[GO-SAIL] cancel job {%s} successfully\n", job.name) }() } @@ -284,13 +284,13 @@ func (j *TaskJob) RunAt(crontabExpr string) (cancel func()) { jobID, jobErr := cronJob.AddFunc(crontabExpr, wrappedTaskFunc) if jobErr != nil { - fmt.Printf("[go-sail] task schedule add job failed: %v\n", jobErr.Error()) + fmt.Printf("[GO-SAIL] add job failed: %v\n", jobErr.Error()) } cancel = func() { go func() { cronJob.Remove(jobID) - fmt.Printf("[go-sail] task schedule cancel job {%s} successfully\n", j.name) + fmt.Printf("[GO-SAIL] cancel job {%s} successfully\n", j.name) }() }