diff --git a/dialer.go b/dialer.go index 5f8fcac..ba72592 100644 --- a/dialer.go +++ b/dialer.go @@ -24,7 +24,7 @@ type Dialer struct { DualStack bool FallbackDelay time.Duration KeepAlive time.Duration - BlacklistTTL time.Duration + DenylistTTL time.Duration Resolver *Resolver } @@ -80,8 +80,8 @@ func (d *Dialer) DialContext(ctx context.Context, network string, address string break } - if resolver.Blacklist != nil { - resolver.Blacklist.Blacklist(addr.Addr, time.Now().Add(d.blacklistTTL())) + if resolver.Denylist != nil { + resolver.Denylist.Denylist(addr.Addr, time.Now().Add(d.denylistTTL())) } } @@ -95,8 +95,8 @@ func (d *Dialer) resolver() *Resolver { return DefaultResolver } -func (d *Dialer) blacklistTTL() time.Duration { - if ttl := d.BlacklistTTL; ttl != 0 { +func (d *Dialer) denylistTTL() time.Duration { + if ttl := d.DenylistTTL; ttl != 0 { return ttl } return 1 * time.Second diff --git a/dialer_test.go b/dialer_test.go index 1621168..3eee3a2 100644 --- a/dialer_test.go +++ b/dialer_test.go @@ -15,7 +15,7 @@ func TestDialer(t *testing.T) { t.Run("dialing existing services results in a connection being established to one of the endpoints", testDialerDialExistingService) - t.Run("dialing non-existing services results in blacklisting the endpoints and an error after a couple of attempts", + t.Run("dialing non-existing services results in denylisting the endpoints and an error after a couple of attempts", testDialerDialNonExistingService) } @@ -78,8 +78,8 @@ func testDialerDialNonExistingService(t *testing.T) { DialContext: (&Dialer{ Timeout: 10 * time.Millisecond, Resolver: &Resolver{ - Client: consulClient, - Blacklist: &ResolverBlacklist{}, + Client: consulClient, + Denylist: &ResolverDenylist{}, }, }).DialContext, }, diff --git a/httpconsul/transport.go b/httpconsul/transport.go index 5286d29..3996f5a 100644 --- a/httpconsul/transport.go +++ b/httpconsul/transport.go @@ -72,9 +72,9 @@ func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { break } - if t.rslv.Blacklist != nil { - // TODO: make the blacklist TTL configurable here? - t.rslv.Blacklist.Blacklist(addr.Addr, time.Now().Add(1*time.Second)) + if t.rslv.Denylist != nil { + // TODO: make the denylist TTL configurable here? + t.rslv.Denylist.Denylist(addr.Addr, time.Now().Add(1*time.Second)) } } diff --git a/httpconsul/transport_test.go b/httpconsul/transport_test.go index 18c6be3..b651de5 100644 --- a/httpconsul/transport_test.go +++ b/httpconsul/transport_test.go @@ -18,7 +18,7 @@ func TestTransport(t *testing.T) { t.Run("sending requests to existing services results in a getting a response from one of the endpoints", testTransportRequestExistingService) - t.Run("sending requests to non-existing services results in blacklisting the endpoints and an error after a couple of attempts", + t.Run("sending requests to non-existing services results in denylisting the endpoints and an error after a couple of attempts", testTransportRequestNonExistingService) } @@ -80,8 +80,8 @@ func testTransportRequestNonExistingService(t *testing.T) { }).DialContext, }, &consul.Resolver{ - Client: consulClient, - Blacklist: &consul.ResolverBlacklist{}, + Client: consulClient, + Denylist: &consul.ResolverDenylist{}, }, ), } diff --git a/resolver.go b/resolver.go index 4523888..6e5d9fe 100644 --- a/resolver.go +++ b/resolver.go @@ -55,8 +55,8 @@ type Resolver struct { Cache *ResolverCache // This field may be set to allow the resolver to support temporarily - // blacklisting addresses that are known to be unreachable. - Blacklist *ResolverBlacklist + // denying addresses that are known to be unreachable. + Denylist *ResolverDenylist // Agent is used to set the origin from which the distance to each endpoints // are computed. If nil, DefaultAgent is used instead. @@ -129,8 +129,8 @@ func (rslv *Resolver) LookupServiceInto(ctx context.Context, name string, list [ return nil, err } - if rslv.Blacklist != nil { - list = rslv.Blacklist.Filter(list, time.Now()) + if rslv.Denylist != nil { + list = rslv.Denylist.Filter(list, time.Now()) } if rslv.Balancer != nil { @@ -260,7 +260,7 @@ func (rslv *Resolver) tomography() *Tomography { var DefaultResolver = &Resolver{ OnlyPassing: true, Cache: &ResolverCache{Balancer: MultiBalancer(defaultCacheBalancer(), &Shuffler{})}, - Blacklist: &ResolverBlacklist{}, + Denylist: &ResolverDenylist{}, Balancer: &LoadBalancer{New: func() Balancer { return &RoundRobin{} }}, Sort: WeightedShuffleOnRTT, } @@ -530,71 +530,71 @@ func splitNameID(s string) (name string, id string) { return } -// ResolverBlacklist implements a negative caching for Resolver instances. +// ResolverDenylist implements a negative caching for Resolver instances. // It works by registering addresses that should be filtered out of a service -// name resolution result, with a deadline at which the address blacklist will +// name resolution result, with a deadline at which the address denylist will // expire. -type ResolverBlacklist struct { +type ResolverDenylist struct { length int64 // number of items in the map version uint32 // counter for cleaning up the resolver map cleaning uint32 // lock to ensure only one goroutine cleans the map - addrs unsafe.Pointer // *blacklistCache + addrs unsafe.Pointer // *denylistCache } const ( - resolverBlacklistCleanupInterval = 1000 + resolverDenylistCleanupInterval = 1000 ) -// Blacklist adds a blacklisted address, which expires and expireAt is reached. -func (blacklist *ResolverBlacklist) Blacklist(addr net.Addr, expireAt time.Time) { - atomic.AddInt64(&blacklist.length, 1) +// Denylist adds a denied address, which expires and expireAt is reached. +func (denylist *ResolverDenylist) Denylist(addr net.Addr, expireAt time.Time) { + atomic.AddInt64(&denylist.length, 1) for { - oldCache := blacklist.loadCache() + oldCache := denylist.loadCache() newCache := oldCache.copy() newCache[addr.String()] = expireAt - if blacklist.compareAndSwapCache(oldCache, &newCache) { + if denylist.compareAndSwapCache(oldCache, &newCache) { break } } } // Filter takes a slice of endpoints and the current time, and returns that -// same slice trimmed, where all blacklisted addresses have been filtered out. -func (blacklist *ResolverBlacklist) Filter(endpoints []Endpoint, now time.Time) []Endpoint { - // In the common case where there is no endpoints in the blacklist, the +// same slice trimmed, where all denied addresses have been filtered out. +func (denylist *ResolverDenylist) Filter(endpoints []Endpoint, now time.Time) []Endpoint { + // In the common case where there is no endpoints in the denylist, the // code takes this fast non-blocking path. - if atomic.LoadInt64(&blacklist.length) == 0 { + if atomic.LoadInt64(&denylist.length) == 0 { return endpoints } - cache := blacklist.cache() + cache := denylist.cache() endpointsLength := 0 for i := range endpoints { - expireAt, blacklisted := cache[endpoints[i].Addr.String()] + expireAt, denylisted := cache[endpoints[i].Addr.String()] - if !blacklisted || now.After(expireAt) { + if !denylisted || now.After(expireAt) { endpoints[endpointsLength] = endpoints[i] endpointsLength++ } } - if version := atomic.AddUint32(&blacklist.version, 1); (version % resolverBlacklistCleanupInterval) == 0 { - if atomic.CompareAndSwapUint32(&blacklist.cleaning, 0, 1) { - blacklist.cleanup(now) - atomic.StoreUint32(&blacklist.cleaning, 0) + if version := atomic.AddUint32(&denylist.version, 1); (version % resolverDenylistCleanupInterval) == 0 { + if atomic.CompareAndSwapUint32(&denylist.cleaning, 0, 1) { + denylist.cleanup(now) + atomic.StoreUint32(&denylist.cleaning, 0) } } return endpoints[:endpointsLength] } -func (blacklist *ResolverBlacklist) cleanup(now time.Time) { +func (denylist *ResolverDenylist) cleanup(now time.Time) { for { deleted := int64(0) - oldCache := blacklist.loadCache() + oldCache := denylist.loadCache() newCache := oldCache.copy() for addr, expireAt := range *oldCache { @@ -604,33 +604,33 @@ func (blacklist *ResolverBlacklist) cleanup(now time.Time) { } } - if blacklist.compareAndSwapCache(oldCache, &newCache) { - atomic.AddInt64(&blacklist.length, -deleted) + if denylist.compareAndSwapCache(oldCache, &newCache) { + atomic.AddInt64(&denylist.length, -deleted) break } } } -func (blacklist *ResolverBlacklist) cache() blacklistCache { - cache := blacklist.loadCache() +func (denylist *ResolverDenylist) cache() denylistCache { + cache := denylist.loadCache() if cache == nil { return nil } return *cache } -func (blacklist *ResolverBlacklist) loadCache() *blacklistCache { - return (*blacklistCache)(atomic.LoadPointer(&blacklist.addrs)) +func (denylist *ResolverDenylist) loadCache() *denylistCache { + return (*denylistCache)(atomic.LoadPointer(&denylist.addrs)) } -func (blacklist *ResolverBlacklist) compareAndSwapCache(old *blacklistCache, new *blacklistCache) bool { - return atomic.CompareAndSwapPointer(&blacklist.addrs, unsafe.Pointer(old), unsafe.Pointer(new)) +func (denylist *ResolverDenylist) compareAndSwapCache(old *denylistCache, new *denylistCache) bool { + return atomic.CompareAndSwapPointer(&denylist.addrs, unsafe.Pointer(old), unsafe.Pointer(new)) } -type blacklistCache map[string]time.Time +type denylistCache map[string]time.Time -func (m *blacklistCache) copy() blacklistCache { - c := make(blacklistCache) +func (m *denylistCache) copy() denylistCache { + c := make(denylistCache) if m != nil { for k, v := range *m { c[k] = v diff --git a/resolver_test.go b/resolver_test.go index 725d8d5..b60cfe1 100644 --- a/resolver_test.go +++ b/resolver_test.go @@ -446,28 +446,28 @@ func BenchmarkResolverCacheIntoResize(b *testing.B) { }) } -func TestResolverBlacklist(t *testing.T) { +func TestResolverDenylist(t *testing.T) { tests := []struct { scenario string - function func(*testing.T, *ResolverBlacklist, []Endpoint) + function func(*testing.T, *ResolverDenylist, []Endpoint) }{ { - scenario: "when no address is blacklisted no address is filtered out", - function: testResolverBlacklistNoFilter, + scenario: "when no address is denylisted no address is filtered out", + function: testResolverDenylistNoFilter, }, { - scenario: "blacklisted addresses are filtered out of the endpoint list", - function: testResolverBlacklistFilter, + scenario: "denied addresses are filtered out of the endpoint list", + function: testResolverDenylistFilter, }, { - scenario: "blacklisted addresses are cleaned up after enough calls to Filter", - function: testResolverBlacklistCleanup, + scenario: "denied addresses are cleaned up after enough calls to Filter", + function: testResolverDenylistCleanup, }, } for _, test := range tests { t.Run(test.scenario, func(t *testing.T) { - blacklist := &ResolverBlacklist{} + denylist := &ResolverDenylist{} endpoints := []Endpoint{ {ID: "A", Addr: newServiceAddr("127.0.0.1", 1000)}, {ID: "B", Addr: newServiceAddr("127.0.0.1", 1001)}, @@ -476,30 +476,30 @@ func TestResolverBlacklist(t *testing.T) { {ID: "E", Addr: newServiceAddr("127.0.0.1", 1004)}, } - test.function(t, blacklist, endpoints) + test.function(t, denylist, endpoints) }) } } -func testResolverBlacklistNoFilter(t *testing.T, blacklist *ResolverBlacklist, endpoints []Endpoint) { +func testResolverDenylistNoFilter(t *testing.T, denylist *ResolverDenylist, endpoints []Endpoint) { now := time.Now() list := make([]Endpoint, len(endpoints)) copy(list, endpoints) - if unfiltered := blacklist.Filter(list, now); !reflect.DeepEqual(unfiltered, endpoints) { + if unfiltered := denylist.Filter(list, now); !reflect.DeepEqual(unfiltered, endpoints) { t.Error("bad endpoint list:") t.Log("expected:", endpoints) t.Log("found: ", unfiltered) } } -func testResolverBlacklistFilter(t *testing.T, blacklist *ResolverBlacklist, endpoints []Endpoint) { +func testResolverDenylistFilter(t *testing.T, denylist *ResolverDenylist, endpoints []Endpoint) { now := time.Now() - blacklist.Blacklist(newServiceAddr("127.0.0.1", 1000), now.Add(time.Second)) - blacklist.Blacklist(newServiceAddr("127.0.0.1", 1003), now.Add(time.Millisecond)) - blacklist.Blacklist(newServiceAddr("192.168.0.1", 8080), now.Add(time.Hour)) + denylist.Denylist(newServiceAddr("127.0.0.1", 1000), now.Add(time.Second)) + denylist.Denylist(newServiceAddr("127.0.0.1", 1003), now.Add(time.Millisecond)) + denylist.Denylist(newServiceAddr("192.168.0.1", 8080), now.Add(time.Hour)) list := make([]Endpoint, len(endpoints)) copy(list, endpoints) @@ -511,38 +511,38 @@ func testResolverBlacklistFilter(t *testing.T, blacklist *ResolverBlacklist, end {ID: "E", Addr: newServiceAddr("127.0.0.1", 1004)}, } - if filtered := blacklist.Filter(list, now.Add(500*time.Millisecond)); !reflect.DeepEqual(filtered, expected) { + if filtered := denylist.Filter(list, now.Add(500*time.Millisecond)); !reflect.DeepEqual(filtered, expected) { t.Error("bad endpoint list:") t.Log("expected:", expected) t.Log("found: ", filtered) } } -func testResolverBlacklistCleanup(t *testing.T, blacklist *ResolverBlacklist, endpoints []Endpoint) { +func testResolverDenylistCleanup(t *testing.T, denylist *ResolverDenylist, endpoints []Endpoint) { now := time.Now() - blacklist.Blacklist(newServiceAddr("127.0.0.1", 1000), now.Add(time.Second)) - blacklist.Blacklist(newServiceAddr("127.0.0.1", 1003), now.Add(time.Millisecond)) - blacklist.Blacklist(newServiceAddr("192.168.0.1", 8080), now.Add(time.Hour)) + denylist.Denylist(newServiceAddr("127.0.0.1", 1000), now.Add(time.Second)) + denylist.Denylist(newServiceAddr("127.0.0.1", 1003), now.Add(time.Millisecond)) + denylist.Denylist(newServiceAddr("192.168.0.1", 8080), now.Add(time.Hour)) - for i := 0; i != (resolverBlacklistCleanupInterval + 1); i++ { + for i := 0; i != (resolverDenylistCleanupInterval + 1); i++ { list := make([]Endpoint, len(endpoints)) copy(list, endpoints) - blacklist.Filter(list, now.Add(2*time.Second)) + denylist.Filter(list, now.Add(2*time.Second)) } - if !reflect.DeepEqual(blacklist.cache(), blacklistCache{ + if !reflect.DeepEqual(denylist.cache(), denylistCache{ "192.168.0.1:8080": now.Add(time.Hour), }) { - t.Error("bad blacklist state:", blacklist.addrs) + t.Error("bad denylist state:", denylist.addrs) } } -func BenchmarkResolverBlacklist(b *testing.B) { +func BenchmarkResolverDenylist(b *testing.B) { b.Run("empty", func(b *testing.B) { now := time.Now() - blacklist := &ResolverBlacklist{} + denylist := &ResolverDenylist{} b.RunParallel(func(pb *testing.PB) { endpoints := []Endpoint{ @@ -553,7 +553,7 @@ func BenchmarkResolverBlacklist(b *testing.B) { } for pb.Next() { - blacklist.Filter(endpoints, now) + denylist.Filter(endpoints, now) } }) }) @@ -562,10 +562,10 @@ func BenchmarkResolverBlacklist(b *testing.B) { now := time.Now() exp := now.Add(time.Minute) - blacklist := &ResolverBlacklist{} - blacklist.Blacklist(newServiceAddr("127.0.0.1", 1002), exp) - blacklist.Blacklist(newServiceAddr("127.0.0.1", 1003), exp) - blacklist.Blacklist(newServiceAddr("127.0.0.1", 1005), exp) + denylist := &ResolverDenylist{} + denylist.Denylist(newServiceAddr("127.0.0.1", 1002), exp) + denylist.Denylist(newServiceAddr("127.0.0.1", 1003), exp) + denylist.Denylist(newServiceAddr("127.0.0.1", 1005), exp) b.RunParallel(func(pb *testing.PB) { endpoints := []Endpoint{ @@ -576,7 +576,7 @@ func BenchmarkResolverBlacklist(b *testing.B) { } for pb.Next() { - blacklist.Filter(endpoints, now) + denylist.Filter(endpoints, now) } }) })