github.com/thanos-io/thanos@v0.32.5/pkg/cache/groupcache_test.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package cache
     5  
     6  import (
     7  	"context"
     8  	"crypto/tls"
     9  	"fmt"
    10  	"net"
    11  	"net/http"
    12  	"os"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/go-kit/log"
    18  	"github.com/prometheus/client_golang/prometheus"
    19  	"github.com/prometheus/common/route"
    20  	"github.com/thanos-io/objstore"
    21  	galaxyhttp "github.com/vimeo/galaxycache/http"
    22  	"golang.org/x/net/http2"
    23  
    24  	"github.com/efficientgo/core/testutil"
    25  	"github.com/thanos-io/thanos/pkg/component"
    26  	"github.com/thanos-io/thanos/pkg/discovery/dns"
    27  	"github.com/thanos-io/thanos/pkg/model"
    28  	"github.com/thanos-io/thanos/pkg/prober"
    29  	httpserver "github.com/thanos-io/thanos/pkg/server/http"
    30  	"github.com/thanos-io/thanos/pkg/store/cache/cachekey"
    31  )
    32  
    33  const basePath = `/_groupcache/`
    34  const groupName = `groupName`
    35  const selfURLH1 = "http://localhost:12345"
    36  const selfURLH2C = "http://localhost:12346"
    37  
    38  func TestMain(m *testing.M) {
    39  	reg := prometheus.NewRegistry()
    40  	router := route.New()
    41  
    42  	bkt := objstore.NewInMemBucket()
    43  	defer bkt.Close()
    44  
    45  	payload := strings.Repeat("foobar", 16*1024/6)
    46  
    47  	if err := bkt.Upload(context.Background(), "test", strings.NewReader(payload)); err != nil {
    48  		fmt.Printf("failed to upload: %s\n", err.Error())
    49  		os.Exit(1)
    50  	}
    51  
    52  	httpServer := httpserver.New(log.NewNopLogger(), nil, component.Bucket, &prober.HTTPProbe{},
    53  		httpserver.WithListen("0.0.0.0:12345"))
    54  	httpServer.Handle("/", router)
    55  	httpServerH2C := httpserver.New(log.NewNopLogger(), nil, component.Bucket, &prober.HTTPProbe{},
    56  		httpserver.WithListen("0.0.0.0:12346"), httpserver.WithEnableH2C(true))
    57  	httpServerH2C.Handle("/", router)
    58  
    59  	cachingBucketConfig := NewCachingBucketConfig()
    60  	cachingBucketConfig.CacheGet("test", nil, func(s string) bool {
    61  		return true
    62  	}, 16*1024, 0*time.Second, 0*time.Second, 0*time.Second)
    63  
    64  	groupCache, err := NewGroupcacheWithConfig(
    65  		log.NewJSONLogger(os.Stderr),
    66  		reg,
    67  		GroupcacheConfig{
    68  			Peers:           []string{selfURLH1},
    69  			SelfURL:         selfURLH1,
    70  			GroupcacheGroup: groupName,
    71  			DNSSDResolver:   dns.MiekgdnsResolverType,
    72  			DNSInterval:     30 * time.Second,
    73  			MaxSize:         model.Bytes(16 * 1024),
    74  		},
    75  		basePath,
    76  		router,
    77  		bkt,
    78  		cachingBucketConfig,
    79  	)
    80  	if err != nil {
    81  		fmt.Printf("failed creating group cache: %s\n", err.Error())
    82  		os.Exit(1)
    83  	}
    84  
    85  	go func() {
    86  		if err = httpServer.ListenAndServe(); err != nil {
    87  			fmt.Printf("failed to listen: %s\n", err.Error())
    88  			os.Exit(1)
    89  		}
    90  	}()
    91  	go func() {
    92  		if err = httpServerH2C.ListenAndServe(); err != nil {
    93  			fmt.Printf("failed to listen: %s\n", err.Error())
    94  			os.Exit(1)
    95  		}
    96  	}()
    97  
    98  	defer httpServer.Shutdown(nil)
    99  	defer httpServerH2C.Shutdown(nil)
   100  
   101  	cachingBucketConfig.SetCacheImplementation(groupCache)
   102  
   103  	exitVal := m.Run()
   104  
   105  	os.Exit(exitVal)
   106  }
   107  
   108  // Benchmark retrieval of one key from one groupcache node.
   109  func BenchmarkGroupcacheRetrieval(b *testing.B) {
   110  	b.Run("h2c", func(b *testing.B) {
   111  		fetcher := galaxyhttp.NewHTTPFetchProtocol(&galaxyhttp.HTTPOptions{
   112  			Transport: &http2.Transport{
   113  				AllowHTTP: true,
   114  				DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
   115  					return net.Dial(network, addr)
   116  				},
   117  			},
   118  			BasePath: basePath,
   119  		})
   120  
   121  		f, err := fetcher.NewFetcher(selfURLH2C)
   122  		testutil.Ok(b, err)
   123  
   124  		b.Run("seq", func(b *testing.B) {
   125  			b.ResetTimer()
   126  			b.ReportAllocs()
   127  
   128  			for i := 0; i < b.N; i++ {
   129  				_, _, err = f.Fetch(context.Background(), groupName, cachekey.BucketCacheKey{Verb: "content", Name: "test"}.String())
   130  				testutil.Ok(b, err)
   131  			}
   132  		})
   133  		b.Run("parallel=500", func(b *testing.B) {
   134  			b.ResetTimer()
   135  			b.ReportAllocs()
   136  
   137  			ch := make(chan struct{})
   138  
   139  			for i := 0; i < 500; i++ {
   140  				go func() {
   141  					for range ch {
   142  						_, _, err = f.Fetch(context.Background(), groupName, cachekey.BucketCacheKey{Verb: "content", Name: "test"}.String())
   143  						testutil.Ok(b, err)
   144  					}
   145  				}()
   146  			}
   147  
   148  			for i := 0; i < b.N; i++ {
   149  				ch <- struct{}{}
   150  			}
   151  			close(ch)
   152  		})
   153  	})
   154  	b.Run("h1, max one TCP connection", func(b *testing.B) {
   155  		fetcher := galaxyhttp.NewHTTPFetchProtocol(&galaxyhttp.HTTPOptions{
   156  			BasePath: basePath,
   157  			Transport: &http.Transport{
   158  				MaxConnsPerHost:     1,
   159  				MaxIdleConnsPerHost: 1,
   160  			},
   161  		})
   162  
   163  		f, err := fetcher.NewFetcher(selfURLH1)
   164  		testutil.Ok(b, err)
   165  
   166  		b.Run("seq", func(b *testing.B) {
   167  			b.ResetTimer()
   168  			b.ReportAllocs()
   169  
   170  			for i := 0; i < b.N; i++ {
   171  				_, _, err = f.Fetch(context.Background(), groupName, cachekey.BucketCacheKey{Verb: "content", Name: "test"}.String())
   172  				testutil.Ok(b, err)
   173  			}
   174  		})
   175  
   176  		b.Run("parallel=500", func(b *testing.B) {
   177  			b.ResetTimer()
   178  			b.ReportAllocs()
   179  
   180  			ch := make(chan struct{})
   181  
   182  			for i := 0; i < 500; i++ {
   183  				go func() {
   184  					for range ch {
   185  						_, _, err = f.Fetch(context.Background(), groupName, cachekey.BucketCacheKey{Verb: "content", Name: "test"}.String())
   186  						testutil.Ok(b, err)
   187  					}
   188  				}()
   189  			}
   190  
   191  			for i := 0; i < b.N; i++ {
   192  				ch <- struct{}{}
   193  			}
   194  			close(ch)
   195  		})
   196  	})
   197  	b.Run("h1, unlimited TCP connections", func(b *testing.B) {
   198  		fetcher := galaxyhttp.NewHTTPFetchProtocol(&galaxyhttp.HTTPOptions{
   199  			BasePath:  basePath,
   200  			Transport: &http.Transport{},
   201  		})
   202  
   203  		f, err := fetcher.NewFetcher(selfURLH1)
   204  		testutil.Ok(b, err)
   205  
   206  		b.Run("seq", func(b *testing.B) {
   207  			b.ResetTimer()
   208  			b.ReportAllocs()
   209  
   210  			for i := 0; i < b.N; i++ {
   211  				_, _, err = f.Fetch(context.Background(), groupName, cachekey.BucketCacheKey{Verb: "content", Name: "test"}.String())
   212  				testutil.Ok(b, err)
   213  			}
   214  		})
   215  
   216  		b.Run("parallel=500", func(b *testing.B) {
   217  			b.ResetTimer()
   218  			b.ReportAllocs()
   219  
   220  			ch := make(chan struct{})
   221  
   222  			for i := 0; i < 500; i++ {
   223  				go func() {
   224  					for range ch {
   225  						_, _, err = f.Fetch(context.Background(), groupName, cachekey.BucketCacheKey{Verb: "content", Name: "test"}.String())
   226  						testutil.Ok(b, err)
   227  					}
   228  				}()
   229  			}
   230  
   231  			for i := 0; i < b.N; i++ {
   232  				ch <- struct{}{}
   233  			}
   234  			close(ch)
   235  		})
   236  	})
   237  
   238  }