Qu'est-ce que ETCD?
ETCD est écrit dans une langue Go pour le stockage des clés systèmes distribués haute performance (KV), découverte de service, l'équilibrage de charge ,, Distributed Lock, des scénarios de gestion de configuration appliqués, semblables à Zookeeper Java. protocole basé Raft, afin d'assurer la cohérence des données.
L'adresse officielle
[etcd.io] https://etcd.io
[github.com] https://github.com/etcd-io/etcd
Installation ETCD
Il y a deux façons d'installer, vous pouvez installer les binaires ou compilez le code source, j'utilise une installation binaire, l'installation d'une autre source que je ne l'ai pas essayé.
En outre, lorsque le montage est pas attaché à un cluster, seule une partie des opérations de base utilisées dans un seul nœud.
Une installation binaire
- Cliquez sur l'adresse suivante, noté dans leur propre système, en sélectionnant différents télécharger package de compression, téléchargez etcd-v3.4.4-darwin-amd64.zip comme MacOs
[ Https://etcd.io/docs/v3.4.0/integrations/ ] https://etcd.io/docs/v3.4.0/integrations/
- L'archive téléchargée, il faut, voir ce qui suit
$ ls ~/Applications/etcd
Documentation README-etcdctl.md README.md READMEv2-etcdctl.md etcd etcdctl
- Les documents ci-dessus, ETCD un serveur, client etcdctl, qui intègre un certain nombre d'Api commun.
En second lieu, l'installation source
Allez parce qu'il est écrit, il peut être utilisé directement go get https://github.com/etcd-io/etcd
téléchargé sur la ligne, mais ce sac ETCD un peu grand, si le réseau n'est pas bon, pas nécessairement à télécharger, je n'étais pas tout entier positif vers le bas.
Donc, si le téléchargement n'est pas vers le bas, vous pouvez essayer de package de téléchargement GitHub essayer d'utiliser le zip, si ne fonctionne toujours pas, l'accélération de téléchargement disponibles dans le pays.
J'ai trouvé un [ en ligne https://www.newbe.pro/Mirrors/Mirrors-Etcd/ ] https://www.newbe.pro/Mirrors/Mirrors-Etcd/, de là directement au téléchargement de l' archive, mettre sous votre Gopath sur la ligne .
Ensuite, entrez le ETCD le répertoire, execute ./build
construit sur la ligne.
début ETCD
Quelle que soit cette façon, de commencer ETCD, d'abord trouver ETCD ce fichier, puis exécutez-le. Le port par défaut 2379 dans votre machine locale, et si vous souhaitez activer le réseau public, spécifiez les paramètres suivants sur la ligne.
$ ~/Applications/etcd/etcd --advertise-client-urls="https://123.33.44.34:2379" --listen-client-urls="https://123.33.44.34:2379"
Démarrage local comme suit
$ ~/Applications/etcd/etcd
[WARNING] Deprecated '--logger=capnslog' flag is set; use '--logger=zap' flag instead
2020-03-11 12:55:38.289362 I | etcdmain: etcd Version: 3.4.4
2020-03-11 12:55:38.289461 I | etcdmain: Git SHA: c65a9e2dd
2020-03-11 12:55:38.289468 I | etcdmain: Go Version: go1.12.12
2020-03-11 12:55:38.289476 I | etcdmain: Go OS/Arch: darwin/amd64
2020-03-11 12:55:38.289482 I | etcdmain: setting maximum number of CPUs to 4, total number of available CPUs is 4
2020-03-11 12:55:38.289492 N | etcdmain: failed to detect default host (default host not supported on darwin_amd64)
2020-03-11 12:55:38.289500 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd
[WARNING] Deprecated '--logger=capnslog' flag is set; use '--logger=zap' flag instead
2020-03-11 12:55:38.292027 I | embed: name = default
2020-03-11 12:55:38.292038 I | embed: data dir = default.etcd
2020-03-11 12:55:38.292045 I | embed: member dir = default.etcd/member
2020-03-11 12:55:38.292050 I | embed: heartbeat = 100ms
2020-03-11 12:55:38.292054 I | embed: election = 1000ms
2020-03-11 12:55:38.292058 I | embed: snapshot count = 100000
2020-03-11 12:55:38.292079 I | embed: advertise client URLs = http://localhost:2379
2020-03-11 12:55:38.407474 I | etcdserver: starting member 8e9e05c52164694d in cluster cdf818194e3a8c32
Eh bien, voir la sortie ci-dessus, le serveur bien démarré, si vous voulez tester, vous pouvez utiliser le test suivant etcdctl.
etcdctl put "task/task1" "task任务"
OK
etcdctl get "task/task1"
task/task1
task任务
code de fonctionnement
Voici quelques opérations simples sur ETCD avec Go, rendez - vous clients peuvent aller sur le site officiel [ https://etcd.io/docs/v3.4.0/integrations/ ] https://etcd.io/docs/v3. 4.0 / intégrations /
Je suis ici est clientv3 ce paquet, qui, lorsqu'il est installé sur le dessus du code source, qui devra télécharger le package, le package est un code de serveur et le client ont le.
Obtenez opération
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
)
func main(){
var (
config clientv3.Config
client *clientv3.Client
kv clientv3.KV
resp *clientv3.GetResponse
err error
)
config = clientv3.Config{
Endpoints:[]string{"localhost:2379"},
DialTimeout:5 * time.Second,
}
if client,err = clientv3.New(config); err != nil {
fmt.Println(err)
return
}
kv = clientv3.NewKV(client)
if resp, err = kv.Get(context.TODO(),"cron/jobs/",clientv3.WithPrefix()); err != nil {
fmt.Println(err)
return
}
for k,v := range resp.Kvs {
fmt.Println(k,v,string(v.Key), string(v.Value))
}
}
opération de renouvellement
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
)
func main(){
var (
config clientv3.Config
client *clientv3.Client
Lease clientv3.Lease
leaseGrantResp *clientv3.LeaseGrantResponse
leaseId clientv3.LeaseID
leaseKeepResp *clientv3.LeaseKeepAliveResponse
leaseKeepRespChan <-chan *clientv3.LeaseKeepAliveResponse
getResp *clientv3.GetResponse
putResp *clientv3.PutResponse
kv clientv3.KV
err error
)
config = clientv3.Config{
Endpoints:[]string{"localhost:2379"},
DialTimeout:5 * time.Second,
}
if client,err = clientv3.New(config); err != nil {
fmt.Println(err)
return
}
Lease = clientv3.NewLease(client)
if leaseGrantResp, err = Lease.Grant(context.TODO(), 10); err != nil {
fmt.Println(err)
}
leaseId = leaseGrantResp.ID
ctx, _ := context.WithTimeout(context.TODO(), 10 * time.Second) //10秒停止续约
if leaseKeepRespChan, err = Lease.KeepAlive(ctx,leaseId); err != nil {
fmt.Println(err)
}
//启动协程,进行续约
go func(){
for {
select {
case leaseKeepResp = <-leaseKeepRespChan:
if leaseKeepResp == nil{
fmt.Println("租约失效了")
goto END
} else {
fmt.Println("收到续约", leaseKeepResp)
}
}
}
END:
}()
kv = clientv3.NewKV(client)
if putResp ,err = kv.Put(context.TODO(),"cron/jobs/job3","job3",clientv3.WithLease(leaseId)); err != nil {
fmt.Println(err)
} else {
fmt.Println("写入成功", putResp.Header.Revision)
}
for {
if getResp, err = kv.Get(context.TODO(),"cron/jobs/job3"); err != nil {
fmt.Println(err)
}
if getResp.Count != 0 {
fmt.Println(getResp.Kvs)
} else {
fmt.Println(" 过期了")
break
}
time.Sleep(2 * time.Second)
}
}
opération op
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
)
func main(){
var (
config clientv3.Config
client *clientv3.Client
opPut clientv3.Op
opGet clientv3.Op
opResp clientv3.OpResponse
kv clientv3.KV
err error
)
config = clientv3.Config{
Endpoints:[]string{"localhost:2379"},
DialTimeout:5 * time.Second,
}
if client,err = clientv3.New(config); err != nil {
fmt.Println(err)
return
}
kv = clientv3.NewKV(client)
opPut = clientv3.OpPut("cron/jobs/job3","job3333")
if opResp, err = kv.Do(context.TODO(),opPut); err != nil {
fmt.Println(err)
return
}
fmt.Println("获取revision", opResp.Put().Header.Revision)
opGet = clientv3.OpGet("cron/jobs/job3")
if opResp ,err = kv.Do(context.TODO(),opGet); err != nil {
fmt.Println(err)
return
}
if len(opResp.Get().Kvs) != 0 {
fmt.Println("获取值:", string(opResp.Get().Kvs[0].Value))
}
}
Serrure répartie simple
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"time"
)
//简单分布式锁
func main(){
var (
config clientv3.Config
client *clientv3.Client
/*opPut clientv3.Op
opGet clientv3.Op
opResp clientv3.OpResponse*/
kv clientv3.KV
txn clientv3.Txn
txnResp *clientv3.TxnResponse
Lease clientv3.Lease
leaseGrantResp *clientv3.LeaseGrantResponse
leaseId clientv3.LeaseID
leaseKeepResp *clientv3.LeaseKeepAliveResponse
leaseKeepRespChan <-chan *clientv3.LeaseKeepAliveResponse
ctx context.Context
cancelFunc context.CancelFunc
err error
)
config = clientv3.Config{
Endpoints:[]string{"localhost:2379"},
DialTimeout:5 * time.Second,
}
if client,err = clientv3.New(config); err != nil {
fmt.Println(err)
return
}
//租约操作
Lease = clientv3.NewLease(client)
if leaseGrantResp, err = Lease.Grant(context.TODO(), 5); err != nil {
fmt.Println(err)
}
leaseId = leaseGrantResp.ID
ctx, cancelFunc = context.WithCancel(context.TODO())
defer cancelFunc()
defer Lease.Revoke(context.TODO(),leaseId)
if leaseKeepRespChan, err = Lease.KeepAlive(ctx,leaseId); err != nil {
fmt.Println(err)
}
//启动协程,进行续约
go func(){
for {
select {
case leaseKeepResp = <-leaseKeepRespChan:
if leaseKeepResp == nil{
fmt.Println("租约失效了")
goto END
} else {
fmt.Println("收到续约", leaseKeepResp)
}
}
}
END:
}()
kv = clientv3.NewKV(client)
//开启事务
txn = kv.Txn(context.TODO())
txn.If(clientv3.Compare(clientv3.CreateRevision("cron/lock/job3"),"=", 0)).
Then(clientv3.OpPut("cron/lock/job3","123",clientv3.WithLease(leaseId))).
Else(clientv3.OpGet("cron/lock/job3"))
if txnResp,err = txn.Commit(); err != nil {
fmt.Println(err)
return
}
if !txnResp.Succeeded {
fmt.Println("OOH,锁被占用了:", string(txnResp.Responses[0].GetResponseRange().Kvs[0].Value))
return
} else {
fmt.Println("抢到了")
}
fmt.Println("处理业务")
time.Sleep( 10 * time.Second)
}
Ce sont les dossiers j'apprends ETCD d'entrée de base et certaines opérations courantes, je l'espère que vous l'aimez, et nous nous réjouissons à certains de vos progrès.