英文:
Two clients acquiring the same lock 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")
}
}
当我运行这段代码时,第二个锁调用永远不会失败,即使它应该失败,因为日志显示锁已经被另一个客户端持有:
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
我在这里漏掉了什么?我是否需要做其他操作以确保第二个客户端不会获取锁?
英文:
I have the following code:
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")
}
}
And when I run it this second lock call never fails, even if it should fail since the lock is already being held by another client as it can be seen by the logs:
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
What am I missing here? Is there something else I must do to make sure the second client doesn't acquire the lock?
答案1
得分: 1
问题是你必须检查从Lock
返回的通道,如果锁已经被持有,通道将为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")
}
}
英文:
Issue was that you have to check the channel that's returned from Lock
, if the lock is already held the channel is 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")
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论