2016-11-29 6 views
1

Ich habe den folgenden Code zu erwerben:Zwei Clients die gleiche Sperre in Consul

package publicservice 

import (
    "time" 
    "github.com/hashicorp/consul/api" 
    "github.com/hashicorp/consul/testutil" 
    "testing" 
) 

func TestAcquireLock(t *testing.T) { 
    consul := testutil.NewTestServer(t) 
    defer consul.Stop() 

    firstClient, err := api.NewClient(&api.Config{ 
     Address: consul.HTTPAddr, 
    }) 

    if err != nil { 
     t.Fatalf("failed to create first client with %v", err) 
    } 

    secondClient, err := api.NewClient(&api.Config{ 
     Address: consul.HTTPAddr, 
    }) 

    if err != nil { 
     t.Fatalf("failed to create second client with %v", err) 
    } 

    lockKey := "sample-lock-key" 

    firstLock, err := firstClient.LockOpts(&api.LockOptions{ 
     Key: lockKey, 
    }) 

    if err != nil { 
     t.Fatalf("failed to create first lock %v", err) 
    } 

    _, err = firstLock.Lock(nil) 

    if err != nil { 
     t.Fatalf("failed to acquire first lock %v", err) 
    } 

    defer firstLock.Unlock() 

    secondLock, err := secondClient.LockOpts(&api.LockOptions{ 
     Key: lockKey, 
     LockTryOnce: true, 
     LockWaitTime: time.Second, 
    }) 

    if err != nil { 
     t.Fatalf("failed to create second lock %v", err) 
    } 

    _, err = secondLock.Lock(nil) 

    if err == nil { 
     t.Fatal("should not have acquired lock here") 
    } 
} 

Und wenn ich es dieses zweite Sperre Anruf laufen nie wird bereits durch ein anderes gehalten, auch wenn es fehlschlagen sollte, da die Sperre nicht Client, wie es von den Protokollen gesehen werden kann:

2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/catalog/nodes (1.115897356s) from=127.0.0.1:50492 
2016/11/29 14:46:25 [DEBUG] http: Request PUT /v1/session/create (939.436µs) from=127.0.0.1:50493 
2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/kv/sample-lock-key?wait=15000ms (269.823µs) from=127.0.0.1:50493 
2016/11/29 14:46:25 [DEBUG] http: Request PUT /v1/kv/sample-lock-key?acquire=aa8fb351-6b6e-8e17-f8d9-fb265c497a9f&flags=3304740253564472344 (899.564µs) from=127.0.0.1:50493 
2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/kv/sample-lock-key?consistent= (112.87µs) from=127.0.0.1:50493 
2016/11/29 14:46:25 [DEBUG] http: Request PUT /v1/session/create (595.554µs) from=127.0.0.1:50494 
2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/kv/sample-lock-key?wait=1000ms (38.602µs) from=127.0.0.1:50494 
2016/11/29 14:46:26 [DEBUG] http: Request GET /v1/kv/sample-lock-key?index=7&wait=999ms (1.007117154s) from=127.0.0.1:50494 
2016/11/29 14:46:26 [DEBUG] http: Request PUT /v1/session/destroy/fd83b8f8-1757-d9d7-6f0e-5defaf26b886 (1.549558ms) from=127.0.0.1:50494 
2016/11/29 14:46:26 [DEBUG] http: Request PUT /v1/kv/sample-lock-key?flags=3304740253564472344&release=aa8fb351-6b6e-8e17-f8d9-fb265c497a9f (1.56451ms) from=127.0.0.1:50495 
2016/11/29 14:46:26 [DEBUG] http: Request GET /v1/kv/sample-lock-key?consistent=&index=7 (1.010637359s) from=127.0.0.1:50493 

Was fehlt mir hier? Gibt es noch etwas, das ich tun muss, um sicherzustellen, dass der zweite Client das Schloss nicht erwirbt?

Antwort

1

Problem war, dass Sie den Kanal zu überprüfen, die von Lock zurückgegeben wird, wenn die Sperre bereits gehalten wird der Kanal nil:

package publicservice 

import (
    "time" 
    "github.com/hashicorp/consul/api" 
    "github.com/hashicorp/consul/testutil" 
    "testing" 
    "github.com/xtgo/uuid" 
) 

func TestAcquireLock(t *testing.T) { 
    consul := testutil.NewTestServer(t) 
    defer consul.Stop() 

    firstClient, err := api.NewClient(&api.Config{ 
     Address: consul.HTTPAddr, 
    }) 

    if err != nil { 
     t.Fatalf("failed to create first client with %v", err) 
    } 

    secondClient, err := api.NewClient(&api.Config{ 
     Address: consul.HTTPAddr, 
    }) 

    if err != nil { 
     t.Fatalf("failed to create second client with %v", err) 
    } 

    lockKey := "sample-lock-key" 

    firstLock, err := firstClient.LockOpts(&api.LockOptions{ 
     Key: lockKey, 
     SessionName: uuid.NewRandom().String(), 
    }) 

    if err != nil { 
     t.Fatalf("failed to create first lock %v", err) 
    } 

    firstResult, err := firstLock.Lock(nil) 

    t.Logf("=====> result for first lock is %v", firstResult) 

    if err != nil { 
     t.Fatalf("failed to acquire first lock %v", err) 
    } 

    defer firstLock.Unlock() 

    secondLock, err := secondClient.LockOpts(&api.LockOptions{ 
     Key: lockKey, 
     LockTryOnce: true, 
     LockWaitTime: time.Second, 
     SessionName: uuid.NewRandom().String(), 
    }) 

    if err != nil { 
     t.Fatalf("failed to create second lock %v", err) 
    } 

    secondResult, err := secondLock.Lock(nil) 

    if secondResult != nil || err != nil { 
     t.Fatal("should not have acquired lock here") 
    } 
} 
+0

Ich weiß, diese Frage ist alt, aber ich habe gerade vor kurzem über sie aus. Wie auch immer, ich bin nur neugierig, was die Logik hinter dem Überprüfen von secondResult ist, um null zu sein. .Lock() blockiert, also nahm ich an, dass jedes Mal, wenn die Blockierung aufgehoben wurde, davon ausgegangen werden kann, dass sie das Schloss erhalten hat. Die Tatsache, dass Sie sagen, dass Sie nach secondResult suchen müssen, um nicht nil zu sein, schlägt mir vor, dass .Lock() nicht wirklich blockiert? – DiderDrogba344

+0

Es nicht, es ist nicht zu, Sie überprüfen das Ergebnis nur zu wissen, ob Sie tatsächlich das Schloss erworben haben oder nicht. –