两个客户端在Consul中获取相同的锁

huangapple go评论93阅读模式
英文:

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")
}
}

huangapple
  • 本文由 发表于 2016年11月30日 03:50:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/40874598.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定